Skip to content
11 changes: 11 additions & 0 deletions src/thorin/be/c/c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ExternType>()) {
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<DefiniteArray>() && "Only strings as argument.");
s.fmt("typedef {} {};\n", first_arg->as<DefiniteArray>()->as_string(), name);
} else {
world().edef(extern_type, "unsupported extern_type");
s.fmt("/* unsupported */");
}
} else {
THORIN_UNREACHABLE;
}
Expand Down
3 changes: 3 additions & 0 deletions src/thorin/rec_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ Stream& Type::stream(Stream& s) const {

if (t->is_vector()) s.fmt(">");
return s;
} else if (auto t = isa<ExternType>()) {
s.fmt("{}", t->name());
return s;
}
THORIN_UNREACHABLE;
}
Expand Down
1 change: 1 addition & 0 deletions src/thorin/tables/nodetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 16 additions & 0 deletions src/thorin/transform/closure_conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<StructType>()->name(), ops.size());
new_types_[type] = new_type;
} else if (type->isa<VariantType>()) {
// 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<VariantType>()->name(), ops.size());
new_types_[type] = new_type;
} else if (type->isa<ExternType>()) {
// 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<ExternType>()->name(), ops.size());
new_types_[type] = new_type;
}

// accept one parameter of order 1 (the return continuation) for function types
Expand All @@ -223,6 +231,14 @@ class ClosureConversion {
StructType* struct_type = const_cast<StructType*>(new_type->as<StructType>());
for (size_t i = 0, e = ops.size(); i != e; ++i)
struct_type->set_op(i, ops[i]);
} else if (type->isa<VariantType>()) {
VariantType* variant_type = const_cast<VariantType*>(new_type->as<VariantType>());
for (size_t i = 0, e = ops.size(); i != e; ++i)
variant_type->set_op(i, ops[i]);
} else if (type->isa<ExternType>()) {
ExternType* extern_type = const_cast<ExternType*>(new_type->as<ExternType>());
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<Type>();
}
Expand Down
8 changes: 8 additions & 0 deletions src/thorin/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -157,6 +161,10 @@ VariantType* World::variant_type(Symbol name, size_t size) {
return put<VariantType>(*this, name, size, Debug());
}

ExternType* World::extern_type(Symbol name, size_t size, Debug dbg) {
return put<ExternType>(*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);
Expand Down
11 changes: 11 additions & 0 deletions src/thorin/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ class VariantType : public NominalType, public TypeOpsMixin<VariantType> {
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:
Expand Down
1 change: 1 addition & 0 deletions src/thorin/world.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class World : public Streamable<World> {
const TupleType* unit_type() { return tuple_type({})->as<TupleType>(); } ///< 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); }
Expand Down