MLIR 23.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
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
19using namespace mlir;
20
21namespace mlir {
22namespace LLVM {
23namespace detail {
24/// Support for translating MLIR LLVM dialect types to LLVM IR.
26public:
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](TokenType) { return llvm::Type::getTokenTy(context); })
62 .Case([this](LLVM::LLVMLabelType) {
63 return llvm::Type::getLabelTy(context);
64 })
65 .Case([this](LLVM::LLVMMetadataType) {
66 return llvm::Type::getMetadataTy(context);
67 })
68 .Case([this](LLVM::LLVMX86AMXType) {
69 return llvm::Type::getX86_AMXTy(context);
70 })
71 .Case<LLVM::LLVMArrayType, LLVM::LLVMByteType, IntegerType,
72 LLVM::LLVMFunctionType, LLVM::LLVMPointerType,
73 LLVM::LLVMStructType, VectorType, LLVM::LLVMTargetExtType,
74 PtrLikeTypeInterface>(
75 [this](auto type) { return this->translate(type); })
76 .DefaultUnreachable("unknown LLVM dialect type");
77
78 // Cache the result of the conversion and return.
79 knownTranslations.try_emplace(type, translated);
80 return translated;
81 }
82
83private:
84 /// Translates the given array type.
85 llvm::Type *translate(LLVM::LLVMArrayType type) {
86 return llvm::ArrayType::get(translateType(type.getElementType()),
87 type.getNumElements());
88 }
89
90 /// Translates the given function type.
91 llvm::Type *translate(LLVM::LLVMFunctionType type) {
93 translateTypes(type.getParams(), paramTypes);
94 return llvm::FunctionType::get(translateType(type.getReturnType()),
95 paramTypes, type.isVarArg());
96 }
97
98 /// Translates the given byte type.
99 llvm::Type *translate(LLVM::LLVMByteType type) {
100 return llvm::Type::getByteNTy(context, type.getBitWidth());
101 }
102
103 /// Translates the given integer type.
104 llvm::Type *translate(IntegerType type) {
105 return llvm::IntegerType::get(context, type.getWidth());
106 }
107
108 /// Translates the given pointer type.
109 llvm::Type *translate(LLVM::LLVMPointerType type) {
110 return llvm::PointerType::get(context, type.getAddressSpace());
111 }
112
113 /// Translates the given structure type, supports both identified and literal
114 /// structs. This will _create_ a new identified structure every time, use
115 /// `convertType` if a structure with the same name must be looked up instead.
116 llvm::Type *translate(LLVM::LLVMStructType type) {
117 SmallVector<llvm::Type *, 8> subtypes;
118 if (!type.isIdentified()) {
119 translateTypes(type.getBody(), subtypes);
120 return llvm::StructType::get(context, subtypes, type.isPacked());
121 }
122
123 llvm::StructType *structType =
124 llvm::StructType::create(context, type.getName());
125 // Mark the type we just created as known so that recursive calls can pick
126 // it up and use directly.
127 knownTranslations.try_emplace(type, structType);
128 if (type.isOpaque())
129 return structType;
130
131 translateTypes(type.getBody(), subtypes);
132 structType->setBody(subtypes, type.isPacked());
133 return structType;
134 }
135
136 /// Translates the given built-in vector type compatible with LLVM.
137 llvm::Type *translate(VectorType type) {
138 assert(LLVM::isCompatibleVectorType(type) &&
139 "expected compatible with LLVM vector type");
140 if (type.isScalable())
141 return llvm::ScalableVectorType::get(translateType(type.getElementType()),
142 type.getNumElements());
143 return llvm::FixedVectorType::get(translateType(type.getElementType()),
144 type.getNumElements());
145 }
146
147 /// Translates the given target extension type.
148 llvm::Type *translate(LLVM::LLVMTargetExtType type) {
149 SmallVector<llvm::Type *> typeParams;
150 translateTypes(type.getTypeParams(), typeParams);
151 return llvm::TargetExtType::get(context, type.getExtTypeName(), typeParams,
152 type.getIntParams());
153 }
154
155 /// Translates the given ptr type.
156 llvm::Type *translate(PtrLikeTypeInterface type) {
157 auto memSpace =
158 dyn_cast<LLVM::LLVMAddrSpaceAttrInterface>(type.getMemorySpace());
159 assert(memSpace && "expected pointer with an LLVM address space");
160 assert(!type.hasPtrMetadata() && "expected pointer without metadata");
161 return llvm::PointerType::get(context, memSpace.getAddressSpace());
162 }
163
164 /// Translates a list of types.
165 void translateTypes(ArrayRef<Type> types,
166 SmallVectorImpl<llvm::Type *> &result) {
167 result.reserve(result.size() + types.size());
168 for (auto type : types)
169 result.push_back(translateType(type));
170 }
171
172 /// Reference to the context in which the LLVM IR types are created.
173 llvm::LLVMContext &context;
174
175 /// Map of known translation. This serves a double purpose: caches translation
176 /// results to avoid repeated recursive calls and makes sure identified
177 /// structs with the same name (that is, equal) are resolved to an existing
178 /// type instead of creating a new type.
179 llvm::DenseMap<Type, llvm::Type *> knownTranslations;
180};
181} // namespace detail
182} // namespace LLVM
183} // namespace mlir
184
186 : impl(new detail::TypeToLLVMIRTranslatorImpl(context)) {}
187
189
191 return impl->translateType(type);
192}
193
195 Type type, const llvm::DataLayout &layout) {
196 return layout.getPrefTypeAlign(translateType(type)).value();
197}
unsigned getPreferredAlignment(Type type, const llvm::DataLayout &layout)
Returns the preferred alignment for the type given the data layout.
llvm::Type * translateType(Type type)
Translates the given MLIR LLVM dialect type to LLVM IR.
TypeToLLVMIRTranslator(llvm::LLVMContext &context)
TypeToLLVMIRTranslatorImpl(llvm::LLVMContext &context)
Constructs a class creating types in the given LLVM context.
llvm::Type * translateType(Type type)
Translates a single type.
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.
Include the generated interface declarations.