Skip to content

Commit 7010f05

Browse files
lkorencxlauko
authored andcommitted
conv:tc: Support basic union lowering to LLVM.
1 parent 60fc90f commit 7010f05

File tree

1 file changed

+87
-2
lines changed

1 file changed

+87
-2
lines changed

include/vast/Conversion/TypeConverters/LLVMTypeConverter.hpp

+87-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#pragma once
44

55
VAST_RELAX_WARNINGS
6+
#include <mlir/Analysis/DataLayoutAnalysis.h>
7+
68
#include <mlir/Conversion/LLVMCommon/TypeConverter.h>
79
#include <mlir/Dialect/Func/IR/FuncOps.h>
810
#include <mlir/Dialect/LLVMIR/LLVMTypes.h>
@@ -211,6 +213,84 @@ namespace vast::conv::tc {
211213
}
212214
};
213215

216+
// Really basic draft of how union lowering works, it should however be able to
217+
// handle most of the usual basic use-cases.
218+
struct union_lowering
219+
{
220+
using self_t = union_lowering;
221+
222+
const mlir::DataLayout &dl;
223+
hl::UnionDeclOp union_decl;
224+
225+
std::vector< mlir_type > fields = {};
226+
227+
union_lowering(const mlir::DataLayout &dl, hl::UnionDeclOp union_decl)
228+
: dl(dl), union_decl(union_decl)
229+
{}
230+
231+
union_lowering(const union_lowering &) = delete;
232+
union_lowering(const union_lowering &&) = delete;
233+
234+
unsigned align(mlir_type t) { return dl.getTypeABIAlignment(t); }
235+
unsigned size(mlir_type t ) { return dl.getTypeSize(t); }
236+
237+
self_t &compute_lowering()
238+
{
239+
mlir_type result;
240+
for (auto field_type : union_decl.getFieldTypes())
241+
result = merge(result, handle_field(storage_type(field_type)));
242+
243+
// TODO(conv:hl-to-ll-geps): Set packed.
244+
// We need to reconstruct the actual union type, should be a method
245+
// of `UnionDeclOp` maybe?
246+
// append_padding_bytes(union_decl.getType(), result);
247+
fields.push_back(result);
248+
249+
return *this;
250+
}
251+
252+
// This maybe should be extracted outside.
253+
mlir_type storage_type(mlir_type type)
254+
{
255+
// convert for mem - basically do things like `i1 -> i8`.
256+
// bitfield has some extras
257+
return mlir::IntegerType::get(type.getContext(), size(type) * 8);
258+
}
259+
260+
void append_padding_bytes(mlir_type union_type, mlir_type field_type)
261+
{
262+
VAST_TODO("Unions that need padding!");
263+
// fields.push_back(array of size difference);
264+
}
265+
266+
mlir_type merge(mlir_type current, mlir_type next)
267+
{
268+
if (!current)
269+
return next;
270+
271+
if (align(current) < align(next))
272+
return next;
273+
274+
if (align(current) == align(next) && size(next) > size(current))
275+
return next;
276+
277+
return current;
278+
}
279+
280+
mlir_type handle_field(mlir_type field_type)
281+
{
282+
// TODO(conv:hl-to-ll-geps): Bitfields.
283+
// TODO(conv:hl-to-ll-geps): Something related to zero initialization.
284+
return field_type;
285+
}
286+
287+
static gap::generator< mlir_type > final_fields(std::vector< mlir_type > fields)
288+
{
289+
for (auto ft : fields)
290+
co_yield ft;
291+
}
292+
};
293+
214294
// Requires that the named types *always* map to llvm struct types.
215295
// TODO(lukas): What about type aliases.
216296
struct FullLLVMTypeConverter : LLVMTypeConverter,
@@ -237,7 +317,13 @@ namespace vast::conv::tc {
237317
if (!def) {
238318
return {};
239319
}
240-
return { def.getFieldTypes() };
320+
if (auto union_decl = mlir::dyn_cast< hl::UnionDeclOp >(*def)) {
321+
auto dl = this->getDataLayoutAnalysis()->getAtOrAbove(union_decl);
322+
auto fields = union_lowering{ dl, union_decl }.compute_lowering().fields;
323+
return { union_lowering::final_fields(std::move(fields)) };
324+
} else {
325+
return { def.getFieldTypes() };
326+
}
241327
}
242328

243329
maybe_type_t convert_elaborated_type(hl::ElaboratedType t) {
@@ -254,5 +340,4 @@ namespace vast::conv::tc {
254340
return { raw };
255341
}
256342
};
257-
258343
} // namespace vast::conv::tc

0 commit comments

Comments
 (0)