diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index 398e6dac4..346f88995 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -369,6 +369,17 @@ 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()) { + 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/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/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/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(); } diff --git a/src/thorin/type.cpp b/src/thorin/type.cpp index 837d6ff2d..e5317a7e1 100644 --- a/src/thorin/type.cpp +++ b/src/thorin/type.cpp @@ -78,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(), num_ops(), debug()); +} + //------------------------------------------------------------------------------ const VectorType* VectorType::scalarize() const { @@ -157,6 +161,10 @@ VariantType* World::variant_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) { 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 8d69b4aa2..f479ba344 100644 --- a/src/thorin/type.h +++ b/src/thorin/type.h @@ -133,6 +133,17 @@ class VariantType : public NominalType, public TypeOpsMixin { friend class World; }; +class ExternType : public NominalType { +private: + 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; + + friend class World; +}; + /// The type of the memory monad. class MemType : public Type { private: diff --git a/src/thorin/world.h b/src/thorin/world.h index 4b77d8072..4777d2ca9 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -110,6 +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, Debug = {}); #define THORIN_ALL_TYPE(T, M) \ const PrimType* type_##T(size_t length = 1) { return prim_type(PrimType_##T, length); }