From 5491ed824683070faf9052dd92f514dea775eb64 Mon Sep 17 00:00:00 2001 From: Matthias Kurtenacker Date: Tue, 1 Apr 2025 16:32:24 +0200 Subject: [PATCH 1/9] Support declaring external types. These can be used to interact with APIs that require us to emit types that we do not currently support in artic, e.g. Matrix Types in SPIRV. Currently, only the C backend supports external types. A typedef is generated, i.e. an ExternType with args `{ "foo" }` and name `"bar"` emits typedef foo bar; --- src/thorin/be/c/c.cpp | 5 +++++ src/thorin/tables/nodetable.h | 1 + src/thorin/type.cpp | 1 + src/thorin/type.h | 20 ++++++++++++++++++++ src/thorin/world.h | 1 + 5 files changed, 28 insertions(+) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index 398e6dac4..60305e2e7 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -369,6 +369,11 @@ std::string CCodeGen::convert(const Type* type) { s.rangei(struct_type->ops(), "\n", [&] (size_t i) { s.fmt("{} {};", convert(struct_type->types()[i]), struct_type->op_name(i)); }); s.fmt("\b\n}} {};\n", name); } + } else if (auto extern_type = type->isa()) { + name = extern_type->name().str(); + assert(extern_type->args().size() == 1 && "External type in C backend unsupported."); + auto first_arg = extern_type->args()[0]; + s.fmt("typedef {} {};", first_arg, name); } else { THORIN_UNREACHABLE; } diff --git a/src/thorin/tables/nodetable.h b/src/thorin/tables/nodetable.h index 8c17d04dc..79938cc94 100644 --- a/src/thorin/tables/nodetable.h +++ b/src/thorin/tables/nodetable.h @@ -57,6 +57,7 @@ THORIN_NODE(Lambda, lambda) THORIN_NODE(MemType, mem) THORIN_NODE(BotType, bot_ty) + THORIN_NODE(ExternType, ext_ty) THORIN_NODE(PtrType, ptr) THORIN_NODE(StructType, struct_type) THORIN_NODE(VariantType, variant_type) diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index 837d6ff2d..ba8aa50d4 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -61,6 +61,7 @@ const Type* MemType ::rebuild(World& w, const Type* , Defs ) const const Type* PrimType ::rebuild(World& w, const Type* , Defs ) const { return w.prim_type(primtype_tag(), length()); } const Type* PtrType ::rebuild(World& w, const Type* , Defs o) const { return w.ptr_type(o[0]->as(), length(), addr_space()); } const Type* TupleType ::rebuild(World& w, const Type* , Defs o) const { return w.tuple_type(defs2types(o)); } +const Type* ExternType ::rebuild(World& w, const Type* , Defs ) const { return w.extern_type(name(), args()); } /* * stub diff --git a/src/thorin/type.h b/src/thorin/type.h index 8d69b4aa2..330af6d9a 100644 --- a/src/thorin/type.h +++ b/src/thorin/type.h @@ -157,6 +157,26 @@ class BottomType : public Type { friend class World; }; +class ExternType : public Type { +private: + ExternType(World& world, Symbol name, std::vector args, Debug dbg) + : Type(world, Node_ExternType, Defs(), dbg) + , name_(name) + , args_(args) + {} + + Symbol name_; + std::vector args_; + +public: + Symbol name() const { return name_; } + std::vector args() const { return args_; } + + const Type* rebuild(World&, const Type*, Defs) const override; + + friend class World; +}; + /// The type of a stack frame. class FrameType : public Type { private: diff --git a/src/thorin/world.h b/src/thorin/world.h index 4b77d8072..c3474ce10 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -116,6 +116,7 @@ class World : public Streamable { #include "thorin/tables/primtypetable.h" const PrimType* prim_type(PrimTypeTag tag, size_t length = 1); const BottomType* bottom_type() { return make(*this, Debug()); } + const ExternType* extern_type(Symbol name, std::vector args) { return make(*this, name, args, Debug()); } const MemType* mem_type() { return make(*this, Debug()); } const FrameType* frame_type() { return make(*this, Debug()); } const PtrType* ptr_type(const Type* pointee, size_t length = 1, AddrSpace addr_space = AddrSpace::Generic); From a0dcf9ef19eea2520995e26face50976020ab407 Mon Sep 17 00:00:00 2001 From: Matthias Kurtenacker Date: Wed, 2 Apr 2025 17:27:25 +0200 Subject: [PATCH 2/9] Bugfix: Extern Types are nominal. --- src/thorin/rec_stream.cpp | 3 +++ src/thorin/type.cpp | 9 ++++++++- src/thorin/type.h | 37 +++++++++++++++++-------------------- src/thorin/world.h | 2 +- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/thorin/rec_stream.cpp b/src/thorin/rec_stream.cpp index 590693e31..9a657efc2 100644 --- a/src/thorin/rec_stream.cpp +++ b/src/thorin/rec_stream.cpp @@ -234,6 +234,9 @@ Stream& Type::stream(Stream& s) const { if (t->is_vector()) s.fmt(">"); return s; + } else if (auto t = isa()) { + s.fmt("{}", t->name()); + return s; } THORIN_UNREACHABLE; } diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index ba8aa50d4..813982ea3 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -61,7 +61,6 @@ const Type* MemType ::rebuild(World& w, const Type* , Defs ) const const Type* PrimType ::rebuild(World& w, const Type* , Defs ) const { return w.prim_type(primtype_tag(), length()); } const Type* PtrType ::rebuild(World& w, const Type* , Defs o) const { return w.ptr_type(o[0]->as(), length(), addr_space()); } const Type* TupleType ::rebuild(World& w, const Type* , Defs o) const { return w.tuple_type(defs2types(o)); } -const Type* ExternType ::rebuild(World& w, const Type* , Defs ) const { return w.extern_type(name(), args()); } /* * stub @@ -79,6 +78,10 @@ VariantType* VariantType::stub(Rewriter& rewriter, const Type*) const { return type; } +ExternType* ExternType::stub(Rewriter& rewriter, const Type*) const { + return rewriter.dst().extern_type(name(), args()); +} + //------------------------------------------------------------------------------ const VectorType* VectorType::scalarize() const { @@ -158,6 +161,10 @@ VariantType* World::variant_type(Symbol name, size_t size) { return put(*this, name, size, Debug()); } +ExternType* World::extern_type(Symbol name, std::vector args) { + return put(*this, name, args, Debug()); +} + const PrimType* World::prim_type(PrimTypeTag tag, size_t length) { size_t i = tag - Begin_PrimType; assert(i < (size_t) Num_PrimTypes); diff --git a/src/thorin/type.h b/src/thorin/type.h index 330af6d9a..8249b2cfd 100644 --- a/src/thorin/type.h +++ b/src/thorin/type.h @@ -133,6 +133,23 @@ class VariantType : public NominalType, public TypeOpsMixin { friend class World; }; +class ExternType : public NominalType { +private: + ExternType(World& world, Symbol name, std::vector args, Debug dbg) + : NominalType(world, Node_ExternType, name, 0, dbg) + , args_(args) + {} + + std::vector args_; + +public: + virtual ExternType* stub(Rewriter&, const Type*) const override; + + std::vector args() const { return args_; } + + friend class World; +}; + /// The type of the memory monad. class MemType : public Type { private: @@ -157,26 +174,6 @@ class BottomType : public Type { friend class World; }; -class ExternType : public Type { -private: - ExternType(World& world, Symbol name, std::vector args, Debug dbg) - : Type(world, Node_ExternType, Defs(), dbg) - , name_(name) - , args_(args) - {} - - Symbol name_; - std::vector args_; - -public: - Symbol name() const { return name_; } - std::vector args() const { return args_; } - - const Type* rebuild(World&, const Type*, Defs) const override; - - friend class World; -}; - /// The type of a stack frame. class FrameType : public Type { private: diff --git a/src/thorin/world.h b/src/thorin/world.h index c3474ce10..2cbbd4a59 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -110,13 +110,13 @@ class World : public Streamable { const TupleType* unit_type() { return tuple_type({})->as(); } ///< Returns unit, i.e., an empty @p TupleType. VariantType* variant_type(Symbol name, size_t size); StructType* struct_type(Symbol name, size_t size); + ExternType* extern_type(Symbol name, std::vector args); #define THORIN_ALL_TYPE(T, M) \ const PrimType* type_##T(size_t length = 1) { return prim_type(PrimType_##T, length); } #include "thorin/tables/primtypetable.h" const PrimType* prim_type(PrimTypeTag tag, size_t length = 1); const BottomType* bottom_type() { return make(*this, Debug()); } - const ExternType* extern_type(Symbol name, std::vector args) { return make(*this, name, args, Debug()); } const MemType* mem_type() { return make(*this, Debug()); } const FrameType* frame_type() { return make(*this, Debug()); } const PtrType* ptr_type(const Type* pointee, size_t length = 1, AddrSpace addr_space = AddrSpace::Generic); From 880c8923f2c62001d66f06bc37ae06ecd2a6cfd5 Mon Sep 17 00:00:00 2001 From: Matthias Kurtenacker Date: Wed, 2 Apr 2025 17:32:56 +0200 Subject: [PATCH 3/9] Add newline to extern type typedef. --- src/thorin/be/c/c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index 60305e2e7..17fa2ab2b 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -373,7 +373,7 @@ std::string CCodeGen::convert(const Type* type) { name = extern_type->name().str(); assert(extern_type->args().size() == 1 && "External type in C backend unsupported."); auto first_arg = extern_type->args()[0]; - s.fmt("typedef {} {};", first_arg, name); + s.fmt("typedef {} {};\n", first_arg, name); } else { THORIN_UNREACHABLE; } From c9088accf2ae8a63b2f73053a0f8f3e258e0a4ce Mon Sep 17 00:00:00 2001 From: Matthias Kurtenacker Date: Fri, 31 Oct 2025 13:46:39 +0100 Subject: [PATCH 4/9] Accept defs as operants in ExternType. --- src/thorin/be/c/c.cpp | 7 ++++--- src/thorin/type.cpp | 10 +++++++--- src/thorin/type.h | 8 ++++---- src/thorin/world.h | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index 17fa2ab2b..e779a5d13 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -371,9 +371,10 @@ std::string CCodeGen::convert(const Type* type) { } } else if (auto extern_type = type->isa()) { name = extern_type->name().str(); - assert(extern_type->args().size() == 1 && "External type in C backend unsupported."); - auto first_arg = extern_type->args()[0]; - s.fmt("typedef {} {};\n", first_arg, name); + assert(extern_type->ops().size() == 1 && "External type in C backend unsupported."); + auto first_arg = extern_type->ops()[0]; + assert(first_arg->isa() && "Only strings as argument."); + s.fmt("typedef {} {};\n", first_arg->as()->as_string(), name); } else { THORIN_UNREACHABLE; } diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index 813982ea3..fe4b47e4b 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -79,7 +79,11 @@ VariantType* VariantType::stub(Rewriter& rewriter, const Type*) const { } ExternType* ExternType::stub(Rewriter& rewriter, const Type*) const { - return rewriter.dst().extern_type(name(), args()); + Array new_ops(ops().size()); + int i = 0; + for (auto o : ops()) + new_ops[i++] = rewriter.instantiate(o); + return rewriter.dst().extern_type(name(), new_ops); } //------------------------------------------------------------------------------ @@ -161,8 +165,8 @@ VariantType* World::variant_type(Symbol name, size_t size) { return put(*this, name, size, Debug()); } -ExternType* World::extern_type(Symbol name, std::vector args) { - return put(*this, name, args, Debug()); +ExternType* World::extern_type(Symbol name, Defs ops) { + return put(*this, name, ops, Debug()); } const PrimType* World::prim_type(PrimTypeTag tag, size_t length) { diff --git a/src/thorin/type.h b/src/thorin/type.h index 8249b2cfd..adcb32003 100644 --- a/src/thorin/type.h +++ b/src/thorin/type.h @@ -135,17 +135,17 @@ class VariantType : public NominalType, public TypeOpsMixin { class ExternType : public NominalType { private: - ExternType(World& world, Symbol name, std::vector args, Debug dbg) + ExternType(World& world, Symbol name, Defs ops, Debug dbg) : NominalType(world, Node_ExternType, name, 0, dbg) - , args_(args) + , ops_(ops) {} - std::vector args_; + Defs ops_; public: virtual ExternType* stub(Rewriter&, const Type*) const override; - std::vector args() const { return args_; } + Defs ops() const { return ops_; } friend class World; }; diff --git a/src/thorin/world.h b/src/thorin/world.h index 2cbbd4a59..381f1fb33 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -110,7 +110,7 @@ class World : public Streamable { const TupleType* unit_type() { return tuple_type({})->as(); } ///< Returns unit, i.e., an empty @p TupleType. VariantType* variant_type(Symbol name, size_t size); StructType* struct_type(Symbol name, size_t size); - ExternType* extern_type(Symbol name, std::vector args); + ExternType* extern_type(Symbol name, Defs ops); #define THORIN_ALL_TYPE(T, M) \ const PrimType* type_##T(size_t length = 1) { return prim_type(PrimType_##T, length); } From ce630c632e5ce6267536cf9fe718e089ef720327 Mon Sep 17 00:00:00 2001 From: Matthias Kurtenacker Date: Fri, 31 Oct 2025 15:05:31 +0100 Subject: [PATCH 5/9] Rename ExternType::ops to ExternType::ext_args to remove any possible name collisions. --- src/thorin/be/c/c.cpp | 4 ++-- src/thorin/type.cpp | 13 +++++++------ src/thorin/type.h | 8 ++++---- src/thorin/world.h | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index e779a5d13..14105cc37 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -371,8 +371,8 @@ std::string CCodeGen::convert(const Type* type) { } } else if (auto extern_type = type->isa()) { name = extern_type->name().str(); - assert(extern_type->ops().size() == 1 && "External type in C backend unsupported."); - auto first_arg = extern_type->ops()[0]; + assert(extern_type->ext_args().size() == 1 && "External type in C backend unsupported."); + auto first_arg = extern_type->ext_args()[0]; assert(first_arg->isa() && "Only strings as argument."); s.fmt("typedef {} {};\n", first_arg->as()->as_string(), name); } else { diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index fe4b47e4b..3d3f29095 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -79,11 +79,12 @@ VariantType* VariantType::stub(Rewriter& rewriter, const Type*) const { } ExternType* ExternType::stub(Rewriter& rewriter, const Type*) const { - Array new_ops(ops().size()); + Array new_args(ext_args().size()); int i = 0; - for (auto o : ops()) - new_ops[i++] = rewriter.instantiate(o); - return rewriter.dst().extern_type(name(), new_ops); + for (auto arg : ext_args()) { + new_args[i++] = rewriter.instantiate(arg); + } + return rewriter.dst().extern_type(name(), new_args); } //------------------------------------------------------------------------------ @@ -165,8 +166,8 @@ VariantType* World::variant_type(Symbol name, size_t size) { return put(*this, name, size, Debug()); } -ExternType* World::extern_type(Symbol name, Defs ops) { - return put(*this, name, ops, Debug()); +ExternType* World::extern_type(Symbol name, Defs ext_args) { + return put(*this, name, ext_args, Debug()); } const PrimType* World::prim_type(PrimTypeTag tag, size_t length) { diff --git a/src/thorin/type.h b/src/thorin/type.h index adcb32003..c4ed1e140 100644 --- a/src/thorin/type.h +++ b/src/thorin/type.h @@ -135,17 +135,17 @@ class VariantType : public NominalType, public TypeOpsMixin { class ExternType : public NominalType { private: - ExternType(World& world, Symbol name, Defs ops, Debug dbg) + ExternType(World& world, Symbol name, Defs ext_args, Debug dbg) : NominalType(world, Node_ExternType, name, 0, dbg) - , ops_(ops) + , ext_args_(ext_args) {} - Defs ops_; + Defs ext_args_; public: virtual ExternType* stub(Rewriter&, const Type*) const override; - Defs ops() const { return ops_; } + Defs ext_args() const { return ext_args_; } friend class World; }; diff --git a/src/thorin/world.h b/src/thorin/world.h index 381f1fb33..890212200 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -110,7 +110,7 @@ class World : public Streamable { const TupleType* unit_type() { return tuple_type({})->as(); } ///< Returns unit, i.e., an empty @p TupleType. VariantType* variant_type(Symbol name, size_t size); StructType* struct_type(Symbol name, size_t size); - ExternType* extern_type(Symbol name, Defs ops); + ExternType* extern_type(Symbol name, Defs ext_args); #define THORIN_ALL_TYPE(T, M) \ const PrimType* type_##T(size_t length = 1) { return prim_type(PrimType_##T, length); } From a92bdeee7b1e03a2e95fe2aa5e41db7d846229db Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 31 Oct 2025 16:01:28 +0100 Subject: [PATCH 6/9] make ExtType a proper nominal node --- src/thorin/type.cpp | 11 +++-------- src/thorin/type.h | 10 ++-------- src/thorin/world.h | 2 +- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index 3d3f29095..9e0e70a56 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -79,12 +79,7 @@ VariantType* VariantType::stub(Rewriter& rewriter, const Type*) const { } ExternType* ExternType::stub(Rewriter& rewriter, const Type*) const { - Array new_args(ext_args().size()); - int i = 0; - for (auto arg : ext_args()) { - new_args[i++] = rewriter.instantiate(arg); - } - return rewriter.dst().extern_type(name(), new_args); + return rewriter.dst().extern_type(name(), num_ops()); } //------------------------------------------------------------------------------ @@ -166,8 +161,8 @@ VariantType* World::variant_type(Symbol name, size_t size) { return put(*this, name, size, Debug()); } -ExternType* World::extern_type(Symbol name, Defs ext_args) { - return put(*this, name, ext_args, Debug()); +ExternType* World::extern_type(Symbol name, size_t size) { + return put(*this, name, size, Debug()); } const PrimType* World::prim_type(PrimTypeTag tag, size_t length) { diff --git a/src/thorin/type.h b/src/thorin/type.h index c4ed1e140..f479ba344 100644 --- a/src/thorin/type.h +++ b/src/thorin/type.h @@ -135,18 +135,12 @@ class VariantType : public NominalType, public TypeOpsMixin { class ExternType : public NominalType { private: - ExternType(World& world, Symbol name, Defs ext_args, Debug dbg) - : NominalType(world, Node_ExternType, name, 0, dbg) - , ext_args_(ext_args) - {} - - Defs ext_args_; + ExternType(World& world, Symbol name, size_t size, Debug dbg) + : NominalType(world, Node_ExternType, name, size, dbg) {} public: virtual ExternType* stub(Rewriter&, const Type*) const override; - Defs ext_args() const { return ext_args_; } - friend class World; }; diff --git a/src/thorin/world.h b/src/thorin/world.h index 890212200..88c5814fb 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -110,7 +110,7 @@ class World : public Streamable { const TupleType* unit_type() { return tuple_type({})->as(); } ///< Returns unit, i.e., an empty @p TupleType. VariantType* variant_type(Symbol name, size_t size); StructType* struct_type(Symbol name, size_t size); - ExternType* extern_type(Symbol name, Defs ext_args); + ExternType* extern_type(Symbol name, size_t size); #define THORIN_ALL_TYPE(T, M) \ const PrimType* type_##T(size_t length = 1) { return prim_type(PrimType_##T, length); } From d1279001184169a6ac0a77c02729f865f67d65b4 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 31 Oct 2025 16:01:38 +0100 Subject: [PATCH 7/9] c: emit ExtType properly --- src/thorin/be/c/c.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index 14105cc37..c332884bd 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -370,9 +370,9 @@ std::string CCodeGen::convert(const Type* type) { s.fmt("\b\n}} {};\n", name); } } else if (auto extern_type = type->isa()) { - name = extern_type->name().str(); - assert(extern_type->ext_args().size() == 1 && "External type in C backend unsupported."); - auto first_arg = extern_type->ext_args()[0]; + types_[extern_type] = name = extern_type->name().str(); + assert(extern_type->num_ops() == 1 && "External type in C backend unsupported."); + auto first_arg = extern_type->op(0); assert(first_arg->isa() && "Only strings as argument."); s.fmt("typedef {} {};\n", first_arg->as()->as_string(), name); } else { From 0bd267f980db98372d649780c707b398efddb770 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 3 Nov 2025 14:35:12 +0100 Subject: [PATCH 8/9] add Debug param to ext_type and use it when emitting --- src/thorin/be/c/c.cpp | 15 ++++++++++----- src/thorin/type.cpp | 6 +++--- src/thorin/world.h | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index c332884bd..346f88995 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -370,11 +370,16 @@ std::string CCodeGen::convert(const Type* type) { s.fmt("\b\n}} {};\n", name); } } else if (auto extern_type = type->isa()) { - types_[extern_type] = name = extern_type->name().str(); - assert(extern_type->num_ops() == 1 && "External type in C backend unsupported."); - auto first_arg = extern_type->op(0); - assert(first_arg->isa() && "Only strings as argument."); - s.fmt("typedef {} {};\n", first_arg->as()->as_string(), name); + if (extern_type->name() == "c.typedef") { + types_[extern_type] = name = extern_type->unique_name(); + assert(extern_type->num_ops() == 1 && "External type in C backend unsupported."); + auto first_arg = extern_type->op(0); + assert(first_arg->isa() && "Only strings as argument."); + s.fmt("typedef {} {};\n", first_arg->as()->as_string(), name); + } else { + world().edef(extern_type, "unsupported extern_type"); + s.fmt("/* unsupported */"); + } } else { THORIN_UNREACHABLE; } diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index 9e0e70a56..e5317a7e1 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -79,7 +79,7 @@ VariantType* VariantType::stub(Rewriter& rewriter, const Type*) const { } ExternType* ExternType::stub(Rewriter& rewriter, const Type*) const { - return rewriter.dst().extern_type(name(), num_ops()); + return rewriter.dst().extern_type(name(), num_ops(), debug()); } //------------------------------------------------------------------------------ @@ -161,8 +161,8 @@ VariantType* World::variant_type(Symbol name, size_t size) { return put(*this, name, size, Debug()); } -ExternType* World::extern_type(Symbol name, size_t size) { - return put(*this, name, size, Debug()); +ExternType* World::extern_type(Symbol name, size_t size, Debug dbg) { + return put(*this, name, size, dbg); } const PrimType* World::prim_type(PrimTypeTag tag, size_t length) { diff --git a/src/thorin/world.h b/src/thorin/world.h index 88c5814fb..4777d2ca9 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -110,7 +110,7 @@ class World : public Streamable { const TupleType* unit_type() { return tuple_type({})->as(); } ///< Returns unit, i.e., an empty @p TupleType. VariantType* variant_type(Symbol name, size_t size); StructType* struct_type(Symbol name, size_t size); - ExternType* extern_type(Symbol name, size_t size); + ExternType* extern_type(Symbol name, size_t size, Debug = {}); #define THORIN_ALL_TYPE(T, M) \ const PrimType* type_##T(size_t length = 1) { return prim_type(PrimType_##T, length); } From 83d8f69c40de3e4983c49df470917f57d79c590a Mon Sep 17 00:00:00 2001 From: Matthias Kurtenacker Date: Wed, 5 Nov 2025 14:37:43 +0100 Subject: [PATCH 9/9] Bugfix: convert VariantType and ExternalType in closure_conversion.cpp --- src/thorin/transform/closure_conversion.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/thorin/transform/closure_conversion.cpp b/src/thorin/transform/closure_conversion.cpp index 2048d77a5..0b937578b 100644 --- a/src/thorin/transform/closure_conversion.cpp +++ b/src/thorin/transform/closure_conversion.cpp @@ -205,6 +205,14 @@ class ClosureConversion { // struct types cannot be rebuilt and need to be put in the map first to avoid infinite recursion new_type = world_.struct_type(type->as()->name(), ops.size()); new_types_[type] = new_type; + } else if (type->isa()) { + // struct types cannot be rebuilt and need to be put in the map first to avoid infinite recursion + new_type = world_.variant_type(type->as()->name(), ops.size()); + new_types_[type] = new_type; + } else if (type->isa()) { + // struct types cannot be rebuilt and need to be put in the map first to avoid infinite recursion + new_type = world_.extern_type(type->as()->name(), ops.size()); + new_types_[type] = new_type; } // accept one parameter of order 1 (the return continuation) for function types @@ -223,6 +231,14 @@ class ClosureConversion { StructType* struct_type = const_cast(new_type->as()); for (size_t i = 0, e = ops.size(); i != e; ++i) struct_type->set_op(i, ops[i]); + } else if (type->isa()) { + VariantType* variant_type = const_cast(new_type->as()); + for (size_t i = 0, e = ops.size(); i != e; ++i) + variant_type->set_op(i, ops[i]); + } else if (type->isa()) { + ExternType* extern_type = const_cast(new_type->as()); + for (size_t i = 0, e = ops.size(); i != e; ++i) + extern_type->set_op(i, ops[i]); } else { new_type = type->rebuild(world_, type->type(), ops)->as(); }