Jlm
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 
8 #include <jlm/rvsdg/control.hpp>
9 
10 #include <llvm/IR/DerivedTypes.h>
11 #include <llvm/IR/Type.h>
12 
13 namespace jlm::llvm
14 {
15 
16 fpsize
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 *
39 TypeConverter::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 
76 std::shared_ptr<const rvsdg::FunctionType>
77 TypeConverter::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 
99 TypeConverter::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 
105 std::shared_ptr<const PointerType>
106 TypeConverter::ConvertPointerType(const ::llvm::PointerType & pointerType)
107 {
108  JLM_ASSERT(pointerType.getAddressSpace() == 0);
109  return PointerType::Create();
110 }
111 
113 TypeConverter::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 
141 TypeConverter::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 *
168 TypeConverter::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 
225 std::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 }
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
Definition: types.hpp:98
static std::shared_ptr< const FixedVectorType > Create(std::shared_ptr< const rvsdg::Type > type, size_t size)
Definition: types.hpp:402
static std::shared_ptr< const FloatingPointType > Create(fpsize size)
Definition: types.cpp:117
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:427
StructType class.
Definition: types.hpp:184
static std::shared_ptr< const StructType > CreateIdentified(const std::string &name, std::vector< std::shared_ptr< const Type >> types, bool isPacked)
Definition: types.hpp:296
static std::shared_ptr< const StructType > CreateLiteral(std::vector< std::shared_ptr< const Type >> types, bool isPacked)
Definition: types.hpp:323
::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.
const std::vector< std::shared_ptr< const jlm::rvsdg::Type > > & Arguments() const noexcept
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
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.
static std::string type(const Node *n)
Definition: view.cpp:255
@ Value
Designate a value type.