brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.0 KiB · 8bd07cd Raw
409 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Target/LLVMIR/DataLayoutImporter.h"10#include "mlir/Dialect/DLTI/DLTI.h"11#include "mlir/IR/Builders.h"12#include "mlir/IR/BuiltinAttributes.h"13#include "mlir/IR/BuiltinTypes.h"14#include "mlir/Interfaces/DataLayoutInterfaces.h"15#include "mlir/Target/LLVMIR/Import.h"16 17#include "llvm/IR/DataLayout.h"18 19using namespace mlir;20using namespace mlir::LLVM;21using namespace mlir::LLVM::detail;22 23/// The default data layout used during the translation.24static 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";27 28FloatType mlir::LLVM::detail::getFloatType(MLIRContext *context,29                                           unsigned width) {30  switch (width) {31  case 16:32    return Float16Type::get(context);33  case 32:34    return Float32Type::get(context);35  case 64:36    return Float64Type::get(context);37  case 80:38    return Float80Type::get(context);39  case 128:40    return Float128Type::get(context);41  default:42    return {};43  }44}45 46FailureOr<StringRef>47DataLayoutImporter::tryToParseAlphaPrefix(StringRef &token) const {48  if (token.empty())49    return failure();50 51  StringRef prefix = token.take_while(isalpha);52  if (prefix.empty())53    return failure();54 55  token.consume_front(prefix);56  return prefix;57}58 59FailureOr<uint64_t> DataLayoutImporter::tryToParseInt(StringRef &token) const {60  uint64_t parameter;61  if (token.consumeInteger(/*Radix=*/10, parameter))62    return failure();63  return parameter;64}65 66template <class T>67static FailureOr<SmallVector<T>> tryToParseIntListImpl(StringRef token) {68  SmallVector<StringRef> tokens;69  token.consume_front(":");70  token.split(tokens, ':');71 72  // Parse an integer list.73  SmallVector<T> 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;78}79 80FailureOr<SmallVector<uint64_t>>81DataLayoutImporter::tryToParseIntList(StringRef token) const {82  return tryToParseIntListImpl<uint64_t>(token);83}84 85FailureOr<DenseIntElementsAttr>86DataLayoutImporter::tryToParseAlignment(StringRef token) const {87  FailureOr<SmallVector<uint64_t>> alignment = tryToParseIntList(token);88  if (failed(alignment))89    return failure();90  if (alignment->empty() || alignment->size() > 2)91    return failure();92 93  // Alignment specifications (such as 32 or 32:64) are of the94  // form <abi>[:<pref>], where abi specifies the minimal alignment and pref the95  // optional preferred alignment. The preferred alignment is set to the minimal96  // alignment if not available.97  uint64_t minimal = (*alignment)[0];98  uint64_t preferred = alignment->size() == 1 ? minimal : (*alignment)[1];99  return DenseIntElementsAttr::get(100      VectorType::get({2}, IntegerType::get(context, 64)),101      {minimal, preferred});102}103 104FailureOr<DenseIntElementsAttr>105DataLayoutImporter::tryToParsePointerAlignment(StringRef token) const {106  FailureOr<SmallVector<uint64_t>> alignment = tryToParseIntList(token);107  if (failed(alignment))108    return failure();109  if (alignment->size() < 2 || alignment->size() > 4)110    return failure();111 112  // Pointer alignment specifications (such as 64:32:64:32 or 32:32) are of113  // the form <size>:<abi>[:<pref>][:<idx>], where size is the pointer size, abi114  // specifies the minimal alignment, pref the optional preferred alignment, and115  // idx the optional index computation bit width. The preferred alignment is116  // set to the minimal alignment if not available and the index computation117  // width is set to the pointer size if not available.118  uint64_t size = (*alignment)[0];119  uint64_t minimal = (*alignment)[1];120  uint64_t preferred = alignment->size() < 3 ? minimal : (*alignment)[2];121  uint64_t idx = alignment->size() < 4 ? size : (*alignment)[3];122  return DenseIntElementsAttr::get<uint64_t>(123      VectorType::get({4}, IntegerType::get(context, 64)),124      {size, minimal, preferred, idx});125}126 127LogicalResult DataLayoutImporter::tryToEmplaceAlignmentEntry(Type type,128                                                             StringRef token) {129  auto key = TypeAttr::get(type);130  if (typeEntries.count(key))131    return success();132 133  FailureOr<DenseIntElementsAttr> params = tryToParseAlignment(token);134  if (failed(params))135    return failure();136 137  typeEntries.try_emplace(key, DataLayoutEntryAttr::get(type, *params));138  return success();139}140 141LogicalResult142DataLayoutImporter::tryToEmplacePointerAlignmentEntry(LLVMPointerType type,143                                                      StringRef token) {144  auto key = TypeAttr::get(type);145  if (typeEntries.count(key))146    return success();147 148  FailureOr<DenseIntElementsAttr> params = tryToParsePointerAlignment(token);149  if (failed(params))150    return failure();151 152  typeEntries.try_emplace(key, DataLayoutEntryAttr::get(type, *params));153  return success();154}155 156LogicalResult157DataLayoutImporter::tryToEmplaceEndiannessEntry(StringRef endianness,158                                                StringRef token) {159  auto key = StringAttr::get(context, DLTIDialect::kDataLayoutEndiannessKey);160  if (keyEntries.count(key))161    return success();162 163  if (!token.empty())164    return failure();165 166  keyEntries.try_emplace(167      key, DataLayoutEntryAttr::get(key, StringAttr::get(context, endianness)));168  return success();169}170 171LogicalResult DataLayoutImporter::tryToEmplaceManglingModeEntry(172    StringRef token, llvm::StringLiteral manglingKey) {173  auto key = StringAttr::get(context, manglingKey);174  if (keyEntries.count(key))175    return success();176 177  token.consume_front(":");178  if (token.empty())179    return failure();180 181  keyEntries.try_emplace(182      key, DataLayoutEntryAttr::get(key, StringAttr::get(context, token)));183  return success();184}185 186LogicalResult187DataLayoutImporter::tryToEmplaceAddrSpaceEntry(StringRef token,188                                               llvm::StringLiteral spaceKey) {189  auto key = StringAttr::get(context, spaceKey);190  if (keyEntries.count(key))191    return success();192 193  FailureOr<uint64_t> space = tryToParseInt(token);194  if (failed(space))195    return failure();196 197  // Only store the address space if it has a non-default value.198  if (*space == 0)199    return success();200  OpBuilder builder(context);201  keyEntries.try_emplace(202      key,203      DataLayoutEntryAttr::get(204          key, builder.getIntegerAttr(205                   builder.getIntegerType(64, /*isSigned=*/false), *space)));206  return success();207}208 209LogicalResult210DataLayoutImporter::tryToEmplaceStackAlignmentEntry(StringRef token) {211  auto key =212      StringAttr::get(context, DLTIDialect::kDataLayoutStackAlignmentKey);213  if (keyEntries.count(key))214    return success();215 216  FailureOr<uint64_t> alignment = tryToParseInt(token);217  if (failed(alignment))218    return failure();219 220  // Stack alignment shouldn't be zero.221  if (*alignment == 0)222    return failure();223  OpBuilder builder(context);224  keyEntries.try_emplace(key, DataLayoutEntryAttr::get(225                                  key, builder.getI64IntegerAttr(*alignment)));226  return success();227}228 229LogicalResult DataLayoutImporter::tryToEmplaceFunctionPointerAlignmentEntry(230    StringRef fnPtrString, StringRef token) {231  auto key = StringAttr::get(232      context, DLTIDialect::kDataLayoutFunctionPointerAlignmentKey);233  if (keyEntries.count(key))234    return success();235 236  // The data layout entry for "F<type><abi>". <abi> is the aligment value,237  // preceded by one of the two possible <types>:238  // "i": The alignment of function pointers is independent of the alignment of239  //      functions, and is a multiple of <abi>.240  // "n": The alignment of function pointers is a multiple of the explicit241  //      alignment specified on the function, and is a multiple of <abi>.242  bool functionDependent = false;243  if (fnPtrString == "n")244    functionDependent = true;245  else if (fnPtrString != "i")246    return failure();247 248  FailureOr<uint64_t> alignment = tryToParseInt(token);249  if (failed(alignment))250    return failure();251 252  keyEntries.try_emplace(253      key, DataLayoutEntryAttr::get(254               key, FunctionPointerAlignmentAttr::get(255                        key.getContext(), *alignment, functionDependent)));256  return success();257}258 259LogicalResult260DataLayoutImporter::tryToEmplaceLegalIntWidthsEntry(StringRef token) {261  auto key =262      StringAttr::get(context, DLTIDialect::kDataLayoutLegalIntWidthsKey);263  if (keyEntries.count(key))264    return success();265 266  FailureOr<SmallVector<int32_t>> intWidths =267      tryToParseIntListImpl<int32_t>(token);268  if (failed(intWidths) || intWidths->empty())269    return failure();270 271  OpBuilder builder(context);272  keyEntries.try_emplace(273      key,274      DataLayoutEntryAttr::get(key, builder.getDenseI32ArrayAttr(*intWidths)));275  return success();276}277 278DataLayoutSpecInterface DataLayoutImporter::dataLayoutSpecFromDataLayoutStr() {279  if (!dataLayoutStr.empty())280    dataLayoutStr += "-";281  dataLayoutStr += kDefaultDataLayout;282 283  // Split the data layout string into tokens separated by a dash.284  SmallVector<StringRef> tokens;285  StringRef(dataLayoutStr).split(tokens, '-');286 287  for (StringRef token : tokens) {288    lastToken = token;289    FailureOr<StringRef> prefix = tryToParseAlphaPrefix(token);290    if (failed(prefix))291      return {};292 293    // Parse the endianness.294    if (*prefix == "e") {295      if (failed(tryToEmplaceEndiannessEntry(296              DLTIDialect::kDataLayoutEndiannessLittle, token)))297        return {};298      continue;299    }300    if (*prefix == "E") {301      if (failed(tryToEmplaceEndiannessEntry(302              DLTIDialect::kDataLayoutEndiannessBig, token)))303        return {};304      continue;305    }306    // Parse the program address space.307    if (*prefix == "P") {308      if (failed(tryToEmplaceAddrSpaceEntry(309              token, DLTIDialect::kDataLayoutProgramMemorySpaceKey)))310        return {};311      continue;312    }313    // Parse the mangling mode.314    if (*prefix == "m") {315      if (failed(tryToEmplaceManglingModeEntry(316              token, DLTIDialect::kDataLayoutManglingModeKey)))317        return {};318      continue;319    }320    // Parse the global address space.321    if (*prefix == "G") {322      if (failed(tryToEmplaceAddrSpaceEntry(323              token, DLTIDialect::kDataLayoutGlobalMemorySpaceKey)))324        return {};325      continue;326    }327    // Parse the alloca address space.328    if (*prefix == "A") {329      if (failed(tryToEmplaceAddrSpaceEntry(330              token, DLTIDialect::kDataLayoutAllocaMemorySpaceKey)))331        return {};332      continue;333    }334    // Parse the stack alignment.335    if (*prefix == "S") {336      if (failed(tryToEmplaceStackAlignmentEntry(token)))337        return {};338      continue;339    }340    // Parse integer alignment specifications.341    if (*prefix == "i") {342      FailureOr<uint64_t> width = tryToParseInt(token);343      if (failed(width))344        return {};345 346      Type type = IntegerType::get(context, *width);347      if (failed(tryToEmplaceAlignmentEntry(type, token)))348        return {};349      continue;350    }351    // Parse float alignment specifications.352    if (*prefix == "f") {353      FailureOr<uint64_t> width = tryToParseInt(token);354      if (failed(width))355        return {};356 357      Type type = getFloatType(context, *width);358      if (failed(tryToEmplaceAlignmentEntry(type, token)))359        return {};360      continue;361    }362    // Parse pointer alignment specifications.363    if (*prefix == "p") {364      FailureOr<uint64_t> space =365          token.starts_with(":") ? 0 : tryToParseInt(token);366      if (failed(space))367        return {};368 369      auto type = LLVMPointerType::get(context, *space);370      if (failed(tryToEmplacePointerAlignmentEntry(type, token)))371        return {};372      continue;373    }374    // Parse native integer widths specifications.375    if (*prefix == "n") {376      if (failed(tryToEmplaceLegalIntWidthsEntry(token)))377        return {};378      continue;379    }380    // Parse function pointer alignment specifications.381    // Note that prefix here is "Fn" or "Fi", not a single character.382    if (prefix->starts_with("F")) {383      StringRef nextPrefix = prefix->drop_front(1);384      if (failed(tryToEmplaceFunctionPointerAlignmentEntry(nextPrefix, token)))385        return {};386      continue;387    }388 389    // Store all tokens that have not been handled.390    unhandledTokens.push_back(lastToken);391  }392 393  // Assemble all entries to a data layout specification.394  SmallVector<DataLayoutEntryInterface> entries;395  entries.reserve(typeEntries.size() + keyEntries.size());396  for (const auto &it : typeEntries)397    entries.push_back(it.second);398  for (const auto &it : keyEntries)399    entries.push_back(it.second);400  return DataLayoutSpecAttr::get(context, entries);401}402 403DataLayoutSpecInterface404mlir::translateDataLayout(const llvm::DataLayout &dataLayout,405                          MLIRContext *context) {406  return DataLayoutImporter(context, dataLayout.getStringRepresentation())407      .getDataLayoutSpec();408}409