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