[Workflow] Roll back some settings since they caused more issues
[llvm-project.git] / mlir / lib / Target / LLVMIR / DataLayoutImporter.cpp
blobd19590600bb9a25c12915661d9d40e86d599488e
1 //===- DataLayoutImporter.cpp - LLVM to MLIR data layout conversion -------===//
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 //===----------------------------------------------------------------------===//
9 #include "DataLayoutImporter.h"
10 #include "mlir/Dialect/DLTI/DLTI.h"
11 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
12 #include "mlir/IR/Builders.h"
13 #include "mlir/IR/BuiltinAttributes.h"
14 #include "mlir/IR/BuiltinTypes.h"
15 #include "mlir/Interfaces/DataLayoutInterfaces.h"
16 #include "mlir/Target/LLVMIR/Import.h"
17 #include "llvm/IR/DataLayout.h"
19 using namespace mlir;
20 using namespace mlir::LLVM;
21 using namespace mlir::LLVM::detail;
23 /// The default data layout used during the translation.
24 static constexpr StringRef kDefaultDataLayout =
25 "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-"
26 "f16:16:16-f64:64:64-f128:128:128";
28 FloatType mlir::LLVM::detail::getFloatType(MLIRContext *context,
29 unsigned width) {
30 switch (width) {
31 case 16:
32 return FloatType::getF16(context);
33 case 32:
34 return FloatType::getF32(context);
35 case 64:
36 return FloatType::getF64(context);
37 case 80:
38 return FloatType::getF80(context);
39 case 128:
40 return FloatType::getF128(context);
41 default:
42 return {};
46 FailureOr<StringRef>
47 DataLayoutImporter::tryToParseAlphaPrefix(StringRef &token) const {
48 if (token.empty())
49 return failure();
51 StringRef prefix = token.take_while(isalpha);
52 if (prefix.empty())
53 return failure();
55 token.consume_front(prefix);
56 return prefix;
59 FailureOr<unsigned> DataLayoutImporter::tryToParseInt(StringRef &token) const {
60 unsigned parameter;
61 if (token.consumeInteger(/*Radix=*/10, parameter))
62 return failure();
63 return parameter;
66 FailureOr<SmallVector<unsigned>>
67 DataLayoutImporter::tryToParseIntList(StringRef token) const {
68 SmallVector<StringRef> tokens;
69 token.consume_front(":");
70 token.split(tokens, ':');
72 // Parse an integer list.
73 SmallVector<unsigned> results(tokens.size());
74 for (auto [result, token] : llvm::zip(results, tokens))
75 if (token.getAsInteger(/*Radix=*/10, result))
76 return failure();
77 return results;
80 FailureOr<DenseIntElementsAttr>
81 DataLayoutImporter::tryToParseAlignment(StringRef token) const {
82 FailureOr<SmallVector<unsigned>> alignment = tryToParseIntList(token);
83 if (failed(alignment))
84 return failure();
85 if (alignment->empty() || alignment->size() > 2)
86 return failure();
88 // Alignment specifications (such as 32 or 32:64) are of the
89 // form <abi>[:<pref>], where abi specifies the minimal alignment and pref the
90 // optional preferred alignment. The preferred alignment is set to the minimal
91 // alignment if not available.
92 unsigned minimal = (*alignment)[0];
93 unsigned preferred = alignment->size() == 1 ? minimal : (*alignment)[1];
94 return DenseIntElementsAttr::get(
95 VectorType::get({2}, IntegerType::get(context, 32)),
96 {minimal, preferred});
99 FailureOr<DenseIntElementsAttr>
100 DataLayoutImporter::tryToParsePointerAlignment(StringRef token) const {
101 FailureOr<SmallVector<unsigned>> alignment = tryToParseIntList(token);
102 if (failed(alignment))
103 return failure();
104 if (alignment->size() < 2 || alignment->size() > 4)
105 return failure();
107 // Pointer alignment specifications (such as 64:32:64:32 or 32:32) are of
108 // the form <size>:<abi>[:<pref>][:<idx>], where size is the pointer size, abi
109 // specifies the minimal alignment, pref the optional preferred alignment, and
110 // idx the optional index computation bit width. The preferred alignment is
111 // set to the minimal alignment if not available and the index computation
112 // width is set to the pointer size if not available.
113 unsigned size = (*alignment)[0];
114 unsigned minimal = (*alignment)[1];
115 unsigned preferred = alignment->size() < 3 ? minimal : (*alignment)[2];
116 unsigned idx = alignment->size() < 4 ? size : (*alignment)[3];
117 return DenseIntElementsAttr::get(
118 VectorType::get({4}, IntegerType::get(context, 32)),
119 {size, minimal, preferred, idx});
122 LogicalResult DataLayoutImporter::tryToEmplaceAlignmentEntry(Type type,
123 StringRef token) {
124 auto key = TypeAttr::get(type);
125 if (typeEntries.count(key))
126 return success();
128 FailureOr<DenseIntElementsAttr> params = tryToParseAlignment(token);
129 if (failed(params))
130 return failure();
132 typeEntries.try_emplace(key, DataLayoutEntryAttr::get(type, *params));
133 return success();
136 LogicalResult
137 DataLayoutImporter::tryToEmplacePointerAlignmentEntry(LLVMPointerType type,
138 StringRef token) {
139 auto key = TypeAttr::get(type);
140 if (typeEntries.count(key))
141 return success();
143 FailureOr<DenseIntElementsAttr> params = tryToParsePointerAlignment(token);
144 if (failed(params))
145 return failure();
147 typeEntries.try_emplace(key, DataLayoutEntryAttr::get(type, *params));
148 return success();
151 LogicalResult
152 DataLayoutImporter::tryToEmplaceEndiannessEntry(StringRef endianness,
153 StringRef token) {
154 auto key = StringAttr::get(context, DLTIDialect::kDataLayoutEndiannessKey);
155 if (keyEntries.count(key))
156 return success();
158 if (!token.empty())
159 return failure();
161 keyEntries.try_emplace(
162 key, DataLayoutEntryAttr::get(key, StringAttr::get(context, endianness)));
163 return success();
166 LogicalResult
167 DataLayoutImporter::tryToEmplaceAllocaAddrSpaceEntry(StringRef token) {
168 auto key =
169 StringAttr::get(context, DLTIDialect::kDataLayoutAllocaMemorySpaceKey);
170 if (keyEntries.count(key))
171 return success();
173 FailureOr<unsigned> space = tryToParseInt(token);
174 if (failed(space))
175 return failure();
177 // Only store the address space if it has a non-default value.
178 if (*space == 0)
179 return success();
180 OpBuilder builder(context);
181 keyEntries.try_emplace(
182 key, DataLayoutEntryAttr::get(key, builder.getUI32IntegerAttr(*space)));
183 return success();
186 LogicalResult
187 DataLayoutImporter::tryToEmplaceStackAlignmentEntry(StringRef token) {
188 auto key =
189 StringAttr::get(context, DLTIDialect::kDataLayoutStackAlignmentKey);
190 if (keyEntries.count(key))
191 return success();
193 FailureOr<unsigned> alignment = tryToParseInt(token);
194 if (failed(alignment))
195 return failure();
197 // Only store the stack alignment if it has a non-default value.
198 if (*alignment == 0)
199 return success();
200 OpBuilder builder(context);
201 keyEntries.try_emplace(key, DataLayoutEntryAttr::get(
202 key, builder.getI32IntegerAttr(*alignment)));
203 return success();
206 void DataLayoutImporter::translateDataLayout(
207 const llvm::DataLayout &llvmDataLayout) {
208 dataLayout = {};
210 // Transform the data layout to its string representation and append the
211 // default data layout string specified in the language reference
212 // (https://llvm.org/docs/LangRef.html#data-layout). The translation then
213 // parses the string and ignores the default value if a specific kind occurs
214 // in both strings. Additionally, the following default values exist:
215 // - non-default address space pointer specifications default to the default
216 // address space pointer specification
217 // - the alloca address space defaults to the default address space.
218 layoutStr = llvmDataLayout.getStringRepresentation();
219 if (!layoutStr.empty())
220 layoutStr += "-";
221 layoutStr += kDefaultDataLayout;
222 StringRef layout(layoutStr);
224 // Split the data layout string into tokens separated by a dash.
225 SmallVector<StringRef> tokens;
226 layout.split(tokens, '-');
228 for (StringRef token : tokens) {
229 lastToken = token;
230 FailureOr<StringRef> prefix = tryToParseAlphaPrefix(token);
231 if (failed(prefix))
232 return;
234 // Parse the endianness.
235 if (*prefix == "e") {
236 if (failed(tryToEmplaceEndiannessEntry(
237 DLTIDialect::kDataLayoutEndiannessLittle, token)))
238 return;
239 continue;
241 if (*prefix == "E") {
242 if (failed(tryToEmplaceEndiannessEntry(
243 DLTIDialect::kDataLayoutEndiannessBig, token)))
244 return;
245 continue;
247 // Parse the alloca address space.
248 if (*prefix == "A") {
249 if (failed(tryToEmplaceAllocaAddrSpaceEntry(token)))
250 return;
251 continue;
253 // Parse the stack alignment.
254 if (*prefix == "S") {
255 if (failed(tryToEmplaceStackAlignmentEntry(token)))
256 return;
257 continue;
259 // Parse integer alignment specifications.
260 if (*prefix == "i") {
261 FailureOr<unsigned> width = tryToParseInt(token);
262 if (failed(width))
263 return;
265 Type type = IntegerType::get(context, *width);
266 if (failed(tryToEmplaceAlignmentEntry(type, token)))
267 return;
268 continue;
270 // Parse float alignment specifications.
271 if (*prefix == "f") {
272 FailureOr<unsigned> width = tryToParseInt(token);
273 if (failed(width))
274 return;
276 Type type = getFloatType(context, *width);
277 if (failed(tryToEmplaceAlignmentEntry(type, token)))
278 return;
279 continue;
281 // Parse pointer alignment specifications.
282 if (*prefix == "p") {
283 FailureOr<unsigned> space =
284 token.starts_with(":") ? 0 : tryToParseInt(token);
285 if (failed(space))
286 return;
288 auto type = LLVMPointerType::get(context, *space);
289 if (failed(tryToEmplacePointerAlignmentEntry(type, token)))
290 return;
291 continue;
294 // Store all tokens that have not been handled.
295 unhandledTokens.push_back(lastToken);
298 // Assemble all entries to a data layout specification.
299 SmallVector<DataLayoutEntryInterface> entries;
300 entries.reserve(typeEntries.size() + keyEntries.size());
301 for (const auto &it : typeEntries)
302 entries.push_back(it.second);
303 for (const auto &it : keyEntries)
304 entries.push_back(it.second);
305 dataLayout = DataLayoutSpecAttr::get(context, entries);
308 DataLayoutSpecInterface
309 mlir::translateDataLayout(const llvm::DataLayout &dataLayout,
310 MLIRContext *context) {
311 return DataLayoutImporter(context, dataLayout).getDataLayout();