Jlm
Loading...
Searching...
No Matches
TypeConverter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
9
10#include <llvm/IR/DerivedTypes.h>
11#include <llvm/IR/Type.h>
12
13namespace jlm::llvm
14{
15
18{
19 JLM_ASSERT(type.isFloatingPointTy());
20
21 switch (type.getTypeID())
22 {
23 case ::llvm::Type::HalfTyID:
24 return fpsize::half;
25 case ::llvm::Type::FloatTyID:
26 return fpsize::flt;
27 case ::llvm::Type::DoubleTyID:
28 return fpsize::dbl;
29 case ::llvm::Type::X86_FP80TyID:
30 return fpsize::x86fp80;
31 case ::llvm::Type::FP128TyID:
32 return fpsize::fp128;
33 default:
34 JLM_UNREACHABLE("TypeConverter::ExtractFloatingPointSize: Unsupported floating point size.");
35 }
36}
37
38::llvm::IntegerType *
39TypeConverter::ConvertBitType(const rvsdg::BitType & bitType, ::llvm::LLVMContext & context)
40{
41 return ::llvm::Type::getIntNTy(context, bitType.nbits());
42}
43
44::llvm::FunctionType *
46 const rvsdg::FunctionType & functionType,
47 ::llvm::LLVMContext & context)
48{
49 bool isVariableArgument = false;
50 std::vector<::llvm::Type *> argumentTypes;
51 for (auto & argumentType : functionType.Arguments())
52 {
53 if (rvsdg::is<VariableArgumentType>(argumentType))
54 {
55 isVariableArgument = true;
56 continue;
57 }
58
59 if (rvsdg::is<IOStateType>(argumentType))
60 continue;
61 if (rvsdg::is<MemoryStateType>(argumentType))
62 continue;
63
64 argumentTypes.push_back(ConvertJlmType(*argumentType, context));
65 }
66
67 // The return type can either be (ValueType, StateType, StateType, ...) if the function has
68 // a return value, or (StateType, StateType, ...) if the function returns void.
69 auto resultType = ::llvm::Type::getVoidTy(context);
70 if (functionType.NumResults() > 0 && functionType.ResultType(0).Kind() == rvsdg::TypeKind::Value)
71 resultType = ConvertJlmType(functionType.ResultType(0), context);
72
73 return ::llvm::FunctionType::get(resultType, argumentTypes, isVariableArgument);
74}
75
76std::shared_ptr<const rvsdg::FunctionType>
77TypeConverter::ConvertFunctionType(const ::llvm::FunctionType & functionType)
78{
79 // Arguments
80 std::vector<std::shared_ptr<const rvsdg::Type>> argumentTypes;
81 for (size_t n = 0; n < functionType.getNumParams(); n++)
82 argumentTypes.push_back(ConvertLlvmType(*functionType.getParamType(n)));
83 if (functionType.isVarArg())
84 argumentTypes.push_back(VariableArgumentType::Create());
85 argumentTypes.push_back(IOStateType::Create());
86 argumentTypes.push_back(MemoryStateType::Create());
87
88 // Results
89 std::vector<std::shared_ptr<const rvsdg::Type>> resultTypes;
90 if (functionType.getReturnType()->getTypeID() != ::llvm::Type::VoidTyID)
91 resultTypes.push_back(ConvertLlvmType(*functionType.getReturnType()));
92 resultTypes.push_back(IOStateType::Create());
93 resultTypes.push_back(MemoryStateType::Create());
94
95 return rvsdg::FunctionType::Create(std::move(argumentTypes), std::move(resultTypes));
96}
97
98::llvm::PointerType *
99TypeConverter::ConvertPointerType(const PointerType &, ::llvm::LLVMContext & context)
100{
101 // FIXME: we default the address space to zero
102 return ::llvm::PointerType::get(context, 0);
103}
104
105std::shared_ptr<const PointerType>
106TypeConverter::ConvertPointerType(const ::llvm::PointerType & pointerType)
107{
108 JLM_ASSERT(pointerType.getAddressSpace() == 0);
109 return PointerType::Create();
110}
111
112::llvm::ArrayType *
113TypeConverter::ConvertArrayType(const ArrayType & type, ::llvm::LLVMContext & context)
114{
115 return ::llvm::ArrayType::get(ConvertJlmType(type.element_type(), context), type.nelements());
116}
117
118::llvm::Type *
120 const FloatingPointType & type,
121 ::llvm::LLVMContext & context)
122{
123 switch (type.size())
124 {
125 case fpsize::half:
126 return ::llvm::Type::getHalfTy(context);
127 case fpsize::flt:
128 return ::llvm::Type::getFloatTy(context);
129 case fpsize::dbl:
130 return ::llvm::Type::getDoubleTy(context);
131 case fpsize::fp128:
132 return ::llvm::Type::getFP128Ty(context);
133 case fpsize::x86fp80:
134 return ::llvm::Type::getX86_FP80Ty(context);
135 default:
136 JLM_UNREACHABLE("TypeConverter::ConvertFloatingPointType: Unhandled floating point size.");
137 }
138}
139
140::llvm::StructType *
141TypeConverter::ConvertStructType(const StructType & type, ::llvm::LLVMContext & context)
142{
143 const auto sharedPtr = std::shared_ptr<const StructType>(std::shared_ptr<void>(), &type);
144
145 if (StructTypeMap_.HasValue(sharedPtr))
146 {
147 const auto llvmStructType = StructTypeMap_.LookupValue(sharedPtr);
148 JLM_ASSERT(&llvmStructType->getContext() == &context);
149 return llvmStructType;
150 }
151
152 std::vector<::llvm::Type *> elements;
153 for (size_t n = 0; n < type.numElements(); n++)
154 elements.push_back(ConvertJlmType(*type.getElementType(n), context));
155
156 // ::llvm::StructType::get() creates a literal struct, while create() creates an identified struct
157 // Giving the create() method an empty name is equivalent to not providing a name.
158 ::llvm::StructType * llvmStructType =
159 type.IsLiteral()
160 ? ::llvm::StructType::get(context, elements, type.IsPacked())
161 : ::llvm::StructType::create(context, elements, type.GetName(), type.IsPacked());
162
163 StructTypeMap_.Insert(llvmStructType, sharedPtr);
164 return llvmStructType;
165}
166
167::llvm::Type *
168TypeConverter::ConvertJlmType(const rvsdg::Type & type, ::llvm::LLVMContext & context)
169{
170 if (const auto bitType = dynamic_cast<const rvsdg::BitType *>(&type))
171 {
172 return ConvertBitType(*bitType, context);
173 }
174
175 if (const auto functionType = dynamic_cast<const rvsdg::FunctionType *>(&type))
176 {
177 return ConvertFunctionType(*functionType, context);
178 }
179
180 if (const auto pointerType = dynamic_cast<const PointerType *>(&type))
181 {
182 return ConvertPointerType(*pointerType, context);
183 }
184
185 if (const auto arrayType = dynamic_cast<const ArrayType *>(&type))
186 {
187 return ConvertArrayType(*arrayType, context);
188 }
189
190 if (const auto controlType = dynamic_cast<const rvsdg::ControlType *>(&type))
191 {
192 return controlType->nalternatives() == 2 ? ::llvm::Type::getInt1Ty(context)
193 : ::llvm::Type::getInt32Ty(context);
194 }
195
196 if (const auto floatingPointType = dynamic_cast<const FloatingPointType *>(&type))
197 {
198 return ConvertFloatingPointType(*floatingPointType, context);
199 }
200
201 if (const auto structType = dynamic_cast<const StructType *>(&type))
202 {
203 return ConvertStructType(*structType, context);
204 }
205
206 if (const auto fixedVectorType = dynamic_cast<const FixedVectorType *>(&type))
207 {
208 return ::llvm::VectorType::get(
209 ConvertJlmType(fixedVectorType->type(), context),
210 fixedVectorType->size(),
211 false);
212 }
213
214 if (const auto scalableVectorType = dynamic_cast<const ScalableVectorType *>(&type))
215 {
216 return ::llvm::VectorType::get(
217 ConvertJlmType(scalableVectorType->type(), context),
218 scalableVectorType->size(),
219 true);
220 }
221
222 JLM_UNREACHABLE("TypeConverter::ConvertJlmType: Unhandled jlm type.");
223}
224
225std::shared_ptr<const rvsdg::Type>
227{
228 switch (type.getTypeID())
229 {
230 case ::llvm::Type::IntegerTyID:
231 {
232 const auto integerType = ::llvm::cast<::llvm::IntegerType>(&type);
233 return rvsdg::BitType::Create(integerType->getBitWidth());
234 }
235 case ::llvm::Type::PointerTyID:
236 return ConvertPointerType(*::llvm::cast<::llvm::PointerType>(&type));
237 case ::llvm::Type::FunctionTyID:
238 return ConvertFunctionType(*::llvm::cast<::llvm::FunctionType>(&type));
239 case ::llvm::Type::HalfTyID:
241 case ::llvm::Type::FloatTyID:
243 case ::llvm::Type::DoubleTyID:
245 case ::llvm::Type::X86_FP80TyID:
247 case ::llvm::Type::FP128TyID:
249 case ::llvm::Type::StructTyID:
250 {
251 const auto structType = ::llvm::cast<::llvm::StructType>(&type);
252 if (StructTypeMap_.HasKey(structType))
253 {
254 return StructTypeMap_.LookupKey(structType);
255 }
256
257 const auto isPacked = structType->isPacked();
258
259 std::vector<std::shared_ptr<const rvsdg::Type>> elementTypes;
260 for (const auto elementType : structType->elements())
261 {
262 elementTypes.push_back(ConvertLlvmType(*elementType));
263 }
264
265 auto jlmType = structType->isLiteral()
266 ? StructType::CreateLiteral(std::move(elementTypes), isPacked)
268 structType->getName().str(),
269 std::move(elementTypes),
270 isPacked);
271
272 StructTypeMap_.Insert(structType, jlmType);
273 return jlmType;
274 }
275 case ::llvm::Type::ArrayTyID:
276 {
277 auto elementType = ConvertLlvmType(*type.getArrayElementType());
278 return ArrayType::Create(std::move(elementType), type.getArrayNumElements());
279 }
280 case ::llvm::Type::FixedVectorTyID:
281 {
282 auto scalarType = ConvertLlvmType(*type.getScalarType());
284 std::move(scalarType),
285 ::llvm::cast<::llvm::FixedVectorType>(&type)->getNumElements());
286 }
287 case ::llvm::Type::ScalableVectorTyID:
288 {
289 auto scalarType = ConvertLlvmType(*type.getScalarType());
291 std::move(scalarType),
292 ::llvm::cast<::llvm::ScalableVectorType>(&type)->getMinNumElements());
293 }
294 default:
295 JLM_UNREACHABLE("TypeConverter::ConvertLlvmType: Unhandled llvm type.");
296 }
297}
298
299}
const rvsdg::Type & element_type() const noexcept
Definition types.hpp:86
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
Definition types.hpp:98
size_t nelements() const noexcept
Definition types.hpp:80
static std::shared_ptr< const FixedVectorType > Create(std::shared_ptr< const rvsdg::Type > type, size_t size)
Definition types.hpp:413
static std::shared_ptr< const FloatingPointType > Create(fpsize size)
Definition types.cpp:117
const fpsize & size() const noexcept
Definition types.hpp:141
static std::shared_ptr< const IOStateType > Create()
Definition types.cpp:343
static std::shared_ptr< const MemoryStateType > Create()
Definition types.cpp:379
PointerType class.
Definition types.hpp:25
static std::shared_ptr< const PointerType > Create()
Definition types.cpp:45
static std::shared_ptr< const ScalableVectorType > Create(std::shared_ptr< const rvsdg::Type > type, size_t size)
Definition types.hpp:438
StructType class.
Definition types.hpp:184
size_t numElements() const noexcept
Definition types.hpp:230
static std::shared_ptr< const StructType > CreateLiteral(std::vector< std::shared_ptr< const Type > > types, bool isPacked)
Definition types.hpp:334
bool IsLiteral() const noexcept
Definition types.hpp:284
static std::shared_ptr< const StructType > CreateIdentified(const std::string &name, std::vector< std::shared_ptr< const Type > > types, bool isPacked)
Definition types.hpp:307
const std::string & GetName() const noexcept
Definition types.hpp:266
std::shared_ptr< const Type > getElementType(const size_t index) const noexcept
Definition types.hpp:236
bool IsPacked() const noexcept
Definition types.hpp:273
::llvm::ArrayType * ConvertArrayType(const ArrayType &type, ::llvm::LLVMContext &context)
::llvm::PointerType * ConvertPointerType(const PointerType &type, ::llvm::LLVMContext &context)
::llvm::IntegerType * ConvertBitType(const rvsdg::BitType &bitType, ::llvm::LLVMContext &context)
::llvm::FunctionType * ConvertFunctionType(const rvsdg::FunctionType &functionType, ::llvm::LLVMContext &context)
std::shared_ptr< const rvsdg::Type > ConvertLlvmType(::llvm::Type &type)
::llvm::Type * ConvertFloatingPointType(const FloatingPointType &type, ::llvm::LLVMContext &context)
static fpsize ExtractFloatingPointSize(const ::llvm::Type &type)
util::BijectiveMap<::llvm::StructType *, std::shared_ptr< const StructType > > StructTypeMap_
::llvm::StructType * ConvertStructType(const StructType &type, ::llvm::LLVMContext &context)
::llvm::Type * ConvertJlmType(const rvsdg::Type &type, ::llvm::LLVMContext &context)
static std::shared_ptr< const VariableArgumentType > Create()
Definition types.cpp:180
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition type.cpp:45
size_t nbits() const noexcept
Definition type.hpp:26
Function type class.
static std::shared_ptr< const FunctionType > Create(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > argumentTypes, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > resultTypes)
size_t NumResults() const noexcept
const jlm::rvsdg::Type & ResultType(size_t index) const noexcept
const std::vector< std::shared_ptr< const jlm::rvsdg::Type > > & Arguments() const noexcept
virtual TypeKind Kind() const noexcept=0
Return the kind of this type.
#define JLM_ASSERT(x)
Definition common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
Global memory state passed between functions.
@ Value
Designate a value type.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872