MLIR  22.0.0git
TypeToLLVM.cpp
Go to the documentation of this file.
1 //===- TypeToLLVM.cpp - type translation from MLIR to LLVM IR -===//
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 
11 #include "mlir/IR/BuiltinTypes.h"
12 
13 #include "llvm/ADT/TypeSwitch.h"
14 #include "llvm/IR/DataLayout.h"
15 #include "llvm/IR/DerivedTypes.h"
16 #include "llvm/IR/Type.h"
17 
18 using namespace mlir;
19 
20 namespace mlir {
21 namespace LLVM {
22 namespace detail {
23 /// Support for translating MLIR LLVM dialect types to LLVM IR.
25 public:
26  /// Constructs a class creating types in the given LLVM context.
27  TypeToLLVMIRTranslatorImpl(llvm::LLVMContext &context) : context(context) {}
28 
29  /// Translates a single type.
30  llvm::Type *translateType(Type type) {
31  // If the conversion is already known, just return it.
32  if (knownTranslations.count(type))
33  return knownTranslations.lookup(type);
34 
35  // Dispatch to an appropriate function.
36  llvm::Type *translated =
38  .Case([this](LLVM::LLVMVoidType) {
39  return llvm::Type::getVoidTy(context);
40  })
41  .Case(
42  [this](Float16Type) { return llvm::Type::getHalfTy(context); })
43  .Case([this](BFloat16Type) {
44  return llvm::Type::getBFloatTy(context);
45  })
46  .Case(
47  [this](Float32Type) { return llvm::Type::getFloatTy(context); })
48  .Case([this](Float64Type) {
49  return llvm::Type::getDoubleTy(context);
50  })
51  .Case([this](Float80Type) {
52  return llvm::Type::getX86_FP80Ty(context);
53  })
54  .Case([this](Float128Type) {
55  return llvm::Type::getFP128Ty(context);
56  })
57  .Case([this](LLVM::LLVMPPCFP128Type) {
58  return llvm::Type::getPPC_FP128Ty(context);
59  })
60  .Case([this](LLVM::LLVMTokenType) {
61  return llvm::Type::getTokenTy(context);
62  })
63  .Case([this](LLVM::LLVMLabelType) {
64  return llvm::Type::getLabelTy(context);
65  })
66  .Case([this](LLVM::LLVMMetadataType) {
67  return llvm::Type::getMetadataTy(context);
68  })
69  .Case([this](LLVM::LLVMX86AMXType) {
70  return llvm::Type::getX86_AMXTy(context);
71  })
72  .Case<LLVM::LLVMArrayType, IntegerType, LLVM::LLVMFunctionType,
73  LLVM::LLVMPointerType, LLVM::LLVMStructType, VectorType,
74  LLVM::LLVMTargetExtType>(
75  [this](auto type) { return this->translate(type); })
76  .Default([](Type t) -> llvm::Type * {
77  llvm_unreachable("unknown LLVM dialect type");
78  });
79 
80  // Cache the result of the conversion and return.
81  knownTranslations.try_emplace(type, translated);
82  return translated;
83  }
84 
85 private:
86  /// Translates the given array type.
87  llvm::Type *translate(LLVM::LLVMArrayType type) {
88  return llvm::ArrayType::get(translateType(type.getElementType()),
89  type.getNumElements());
90  }
91 
92  /// Translates the given function type.
93  llvm::Type *translate(LLVM::LLVMFunctionType type) {
95  translateTypes(type.getParams(), paramTypes);
96  return llvm::FunctionType::get(translateType(type.getReturnType()),
97  paramTypes, type.isVarArg());
98  }
99 
100  /// Translates the given integer type.
101  llvm::Type *translate(IntegerType type) {
102  return llvm::IntegerType::get(context, type.getWidth());
103  }
104 
105  /// Translates the given pointer type.
106  llvm::Type *translate(LLVM::LLVMPointerType type) {
107  return llvm::PointerType::get(context, type.getAddressSpace());
108  }
109 
110  /// Translates the given structure type, supports both identified and literal
111  /// structs. This will _create_ a new identified structure every time, use
112  /// `convertType` if a structure with the same name must be looked up instead.
113  llvm::Type *translate(LLVM::LLVMStructType type) {
115  if (!type.isIdentified()) {
116  translateTypes(type.getBody(), subtypes);
117  return llvm::StructType::get(context, subtypes, type.isPacked());
118  }
119 
120  llvm::StructType *structType =
121  llvm::StructType::create(context, type.getName());
122  // Mark the type we just created as known so that recursive calls can pick
123  // it up and use directly.
124  knownTranslations.try_emplace(type, structType);
125  if (type.isOpaque())
126  return structType;
127 
128  translateTypes(type.getBody(), subtypes);
129  structType->setBody(subtypes, type.isPacked());
130  return structType;
131  }
132 
133  /// Translates the given built-in vector type compatible with LLVM.
134  llvm::Type *translate(VectorType type) {
135  assert(LLVM::isCompatibleVectorType(type) &&
136  "expected compatible with LLVM vector type");
137  if (type.isScalable())
138  return llvm::ScalableVectorType::get(translateType(type.getElementType()),
139  type.getNumElements());
140  return llvm::FixedVectorType::get(translateType(type.getElementType()),
141  type.getNumElements());
142  }
143 
144  /// Translates the given target extension type.
145  llvm::Type *translate(LLVM::LLVMTargetExtType type) {
146  SmallVector<llvm::Type *> typeParams;
147  translateTypes(type.getTypeParams(), typeParams);
148  return llvm::TargetExtType::get(context, type.getExtTypeName(), typeParams,
149  type.getIntParams());
150  }
151 
152  /// Translates a list of types.
153  void translateTypes(ArrayRef<Type> types,
155  result.reserve(result.size() + types.size());
156  for (auto type : types)
157  result.push_back(translateType(type));
158  }
159 
160  /// Reference to the context in which the LLVM IR types are created.
161  llvm::LLVMContext &context;
162 
163  /// Map of known translation. This serves a double purpose: caches translation
164  /// results to avoid repeated recursive calls and makes sure identified
165  /// structs with the same name (that is, equal) are resolved to an existing
166  /// type instead of creating a new type.
167  llvm::DenseMap<Type, llvm::Type *> knownTranslations;
168 };
169 } // namespace detail
170 } // namespace LLVM
171 } // namespace mlir
172 
174  : impl(new detail::TypeToLLVMIRTranslatorImpl(context)) {}
175 
177 
179  return impl->translateType(type);
180 }
181 
183  Type type, const llvm::DataLayout &layout) {
184  return layout.getPrefTypeAlign(translateType(type)).value();
185 }
unsigned getPreferredAlignment(Type type, const llvm::DataLayout &layout)
Returns the preferred alignment for the type given the data layout.
Definition: TypeToLLVM.cpp:182
llvm::Type * translateType(Type type)
Translates the given MLIR LLVM dialect type to LLVM IR.
Definition: TypeToLLVM.cpp:178
TypeToLLVMIRTranslator(llvm::LLVMContext &context)
Definition: TypeToLLVM.cpp:173
Support for translating MLIR LLVM dialect types to LLVM IR.
Definition: TypeToLLVM.cpp:24
TypeToLLVMIRTranslatorImpl(llvm::LLVMContext &context)
Constructs a class creating types in the given LLVM context.
Definition: TypeToLLVM.cpp:27
llvm::Type * translateType(Type type)
Translates a single type.
Definition: TypeToLLVM.cpp:30
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:813
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...