1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "banjo/tables_generator.h"
6 
7 #include "banjo/names.h"
8 
9 namespace banjo {
10 
11 namespace {
12 
13 constexpr auto kIndent = "    ";
14 
operator <<(std::ostream & stream,StringView view)15 std::ostream& operator<<(std::ostream& stream, StringView view) {
16     stream.rdbuf()->sputn(view.data(), view.size());
17     return stream;
18 }
19 
Emit(std::ostream * file,StringView data)20 void Emit(std::ostream* file, StringView data) {
21     *file << data;
22 }
23 
EmitNewlineAndIndent(std::ostream * file,size_t indent_level)24 void EmitNewlineAndIndent(std::ostream* file, size_t indent_level) {
25     *file << "\n";
26     while (indent_level--)
27         *file << kIndent;
28 }
29 
EmitArrayBegin(std::ostream * file)30 void EmitArrayBegin(std::ostream* file) {
31     *file << "{";
32 }
33 
EmitArraySeparator(std::ostream * file,size_t indent_level)34 void EmitArraySeparator(std::ostream* file, size_t indent_level) {
35     *file << ",";
36     EmitNewlineAndIndent(file, indent_level);
37 }
38 
EmitArrayEnd(std::ostream * file)39 void EmitArrayEnd(std::ostream* file) {
40     *file << "}";
41 }
42 
Emit(std::ostream * file,uint32_t value)43 void Emit(std::ostream* file, uint32_t value) {
44     *file << value;
45 }
46 
Emit(std::ostream * file,types::HandleSubtype handle_subtype)47 void Emit(std::ostream* file, types::HandleSubtype handle_subtype) {
48     Emit(file, NameHandleZXObjType(handle_subtype));
49 }
50 
Emit(std::ostream * file,types::Nullability nullability)51 void Emit(std::ostream* file, types::Nullability nullability) {
52     switch (nullability) {
53     case types::Nullability::kNullable:
54         Emit(file, "::banjo::kNullable");
55         break;
56     case types::Nullability::kNonnullable:
57         Emit(file, "::banjo::kNonnullable");
58         break;
59     }
60 }
61 
62 } // namespace
63 
GenerateInclude(StringView filename)64 void TablesGenerator::GenerateInclude(StringView filename) {
65     Emit(&tables_file_, "#include ");
66     Emit(&tables_file_, filename);
67     Emit(&tables_file_, "\n");
68 }
69 
GenerateFilePreamble()70 void TablesGenerator::GenerateFilePreamble() {
71     Emit(&tables_file_, "// WARNING: This file is machine generated by banjoc.\n\n");
72     GenerateInclude("<lib/banjo/internal.h>");
73     Emit(&tables_file_, "\nextern \"C\" {\n");
74     Emit(&tables_file_, "\n");
75 }
76 
GenerateFilePostamble()77 void TablesGenerator::GenerateFilePostamble() {
78     Emit(&tables_file_, "} // extern \"C\"\n");
79 }
80 
81 template <typename Collection>
GenerateArray(const Collection & collection)82 void TablesGenerator::GenerateArray(const Collection& collection) {
83     EmitArrayBegin(&tables_file_);
84 
85     if (!collection.empty())
86         EmitNewlineAndIndent(&tables_file_, ++indent_level_);
87 
88     for (size_t i = 0; i < collection.size(); ++i) {
89         if (i)
90             EmitArraySeparator(&tables_file_, indent_level_);
91         Generate(collection[i]);
92     }
93 
94     if (!collection.empty())
95         EmitNewlineAndIndent(&tables_file_, --indent_level_);
96 
97     EmitArrayEnd(&tables_file_);
98 }
99 
Generate(const coded::StructType & struct_type)100 void TablesGenerator::Generate(const coded::StructType& struct_type) {
101     Emit(&tables_file_, "static const ::banjo::BanjoField ");
102     Emit(&tables_file_, NameFields(struct_type.coded_name));
103     Emit(&tables_file_, "[] = ");
104     GenerateArray(struct_type.fields);
105     Emit(&tables_file_, ";\n");
106 
107     Emit(&tables_file_, "const banjo_type_t ");
108     Emit(&tables_file_, NameTable(struct_type.coded_name));
109     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedStruct(");
110     Emit(&tables_file_, NameFields(struct_type.coded_name));
111     Emit(&tables_file_, ", ");
112     Emit(&tables_file_, struct_type.fields.size());
113     Emit(&tables_file_, ", ");
114     Emit(&tables_file_, struct_type.size);
115     Emit(&tables_file_, ", \"");
116     Emit(&tables_file_, struct_type.qname);
117     Emit(&tables_file_, "\"));\n\n");
118 }
119 
Generate(const coded::UnionType & union_type)120 void TablesGenerator::Generate(const coded::UnionType& union_type) {
121     Emit(&tables_file_, "static const banjo_type_t* ");
122     Emit(&tables_file_, NameMembers(union_type.coded_name));
123     Emit(&tables_file_, "[] = ");
124     GenerateArray(union_type.types);
125     Emit(&tables_file_, ";\n");
126 
127     Emit(&tables_file_, "const banjo_type_t ");
128     Emit(&tables_file_, NameTable(union_type.coded_name));
129     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedUnion(");
130     Emit(&tables_file_, NameMembers(union_type.coded_name));
131     Emit(&tables_file_, ", ");
132     Emit(&tables_file_, union_type.types.size());
133     Emit(&tables_file_, ", ");
134     Emit(&tables_file_, union_type.data_offset);
135     Emit(&tables_file_, ", ");
136     Emit(&tables_file_, union_type.size);
137     Emit(&tables_file_, ", \"");
138     Emit(&tables_file_, union_type.qname);
139     Emit(&tables_file_, "\"));\n\n");
140 }
141 
Generate(const coded::MessageType & message_type)142 void TablesGenerator::Generate(const coded::MessageType& message_type) {
143     Emit(&tables_file_, "extern const banjo_type_t ");
144     Emit(&tables_file_, NameTable(message_type.coded_name));
145     Emit(&tables_file_, ";\n");
146 
147     Emit(&tables_file_, "static const ::banjo::BanjoField ");
148     Emit(&tables_file_, NameFields(message_type.coded_name));
149     Emit(&tables_file_, "[] = ");
150     GenerateArray(message_type.fields);
151     Emit(&tables_file_, ";\n");
152 
153     Emit(&tables_file_, "const banjo_type_t ");
154     Emit(&tables_file_, NameTable(message_type.coded_name));
155     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedStruct(");
156     Emit(&tables_file_, NameFields(message_type.coded_name));
157     Emit(&tables_file_, ", ");
158     Emit(&tables_file_, message_type.fields.size());
159     Emit(&tables_file_, ", ");
160     Emit(&tables_file_, message_type.size);
161     Emit(&tables_file_, ", \"");
162     Emit(&tables_file_, message_type.qname);
163     Emit(&tables_file_, "\"));\n\n");
164 }
165 
Generate(const coded::HandleType & handle_type)166 void TablesGenerator::Generate(const coded::HandleType& handle_type) {
167     Emit(&tables_file_, "static const banjo_type_t ");
168     Emit(&tables_file_, NameTable(handle_type.coded_name));
169     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedHandle(");
170     Emit(&tables_file_, handle_type.subtype);
171     Emit(&tables_file_, ", ");
172     Emit(&tables_file_, handle_type.nullability);
173     Emit(&tables_file_, "));\n\n");
174 }
175 
Generate(const coded::RequestHandleType & request_type)176 void TablesGenerator::Generate(const coded::RequestHandleType& request_type) {
177     Emit(&tables_file_, "static const banjo_type_t ");
178     Emit(&tables_file_, NameTable(request_type.coded_name));
179     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedHandle(");
180     Emit(&tables_file_, types::HandleSubtype::kChannel);
181     Emit(&tables_file_, ", ");
182     Emit(&tables_file_, request_type.nullability);
183     Emit(&tables_file_, "));\n\n");
184 }
185 
Generate(const coded::InterfaceHandleType & interface_type)186 void TablesGenerator::Generate(const coded::InterfaceHandleType& interface_type) {
187     Emit(&tables_file_, "static const banjo_type_t ");
188     Emit(&tables_file_, NameTable(interface_type.coded_name));
189     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedHandle(");
190     Emit(&tables_file_, types::HandleSubtype::kChannel);
191     Emit(&tables_file_, ", ");
192     Emit(&tables_file_, interface_type.nullability);
193     Emit(&tables_file_, "));\n\n");
194 }
195 
Generate(const coded::ArrayType & array_type)196 void TablesGenerator::Generate(const coded::ArrayType& array_type) {
197     Emit(&tables_file_, "static const banjo_type_t ");
198     Emit(&tables_file_, NameTable(array_type.coded_name));
199     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedArray(&");
200     Emit(&tables_file_, NameTable(array_type.element_type->coded_name));
201     Emit(&tables_file_, ", ");
202     Emit(&tables_file_, array_type.size);
203     Emit(&tables_file_, ", ");
204     Emit(&tables_file_, array_type.element_size);
205     Emit(&tables_file_, "));\n\n");
206 }
207 
Generate(const coded::StringType & string_type)208 void TablesGenerator::Generate(const coded::StringType& string_type) {
209     Emit(&tables_file_, "static const banjo_type_t ");
210     Emit(&tables_file_, NameTable(string_type.coded_name));
211     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedString(");
212     Emit(&tables_file_, string_type.max_size);
213     Emit(&tables_file_, ", ");
214     Emit(&tables_file_, string_type.nullability);
215     Emit(&tables_file_, "));\n\n");
216 }
217 
Generate(const coded::VectorType & vector_type)218 void TablesGenerator::Generate(const coded::VectorType& vector_type) {
219     Emit(&tables_file_, "static const banjo_type_t ");
220     Emit(&tables_file_, NameTable(vector_type.coded_name));
221     Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedVector(");
222     if (vector_type.element_type->coding_needed == coded::CodingNeeded::kNeeded) {
223         Emit(&tables_file_, "&");
224         Emit(&tables_file_, NameTable(vector_type.element_type->coded_name));
225     } else {
226         Emit(&tables_file_, "nullptr");
227     }
228     Emit(&tables_file_, ", ");
229     Emit(&tables_file_, vector_type.max_count);
230     Emit(&tables_file_, ", ");
231     Emit(&tables_file_, vector_type.element_size);
232     Emit(&tables_file_, ", ");
233     Emit(&tables_file_, vector_type.nullability);
234     Emit(&tables_file_, "));\n\n");
235 }
236 
Generate(const coded::Type * type)237 void TablesGenerator::Generate(const coded::Type* type) {
238     if (type) {
239         Emit(&tables_file_, "&");
240         Emit(&tables_file_, NameTable(type->coded_name));
241     } else {
242         Emit(&tables_file_, "nullptr");
243     }
244 }
245 
Generate(const coded::StructField & field)246 void TablesGenerator::Generate(const coded::StructField& field) {
247     Emit(&tables_file_, "::banjo::BanjoField(&");
248     Emit(&tables_file_, NameTable(field.type->coded_name));
249     Emit(&tables_file_, ", ");
250     Emit(&tables_file_, field.offset);
251     Emit(&tables_file_, ")");
252 }
253 
GeneratePointerIfNeeded(const coded::StructType & struct_type)254 void TablesGenerator::GeneratePointerIfNeeded(const coded::StructType& struct_type) {
255     if (struct_type.referenced_by_pointer) {
256         Emit(&tables_file_, "static const banjo_type_t ");
257         Emit(&tables_file_, NameTable(struct_type.pointer_name));
258         Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedStructPointer(&");
259         Emit(&tables_file_, NameTable(struct_type.coded_name));
260         Emit(&tables_file_, ".coded_struct));\n");
261     }
262 }
263 
GeneratePointerIfNeeded(const coded::UnionType & union_type)264 void TablesGenerator::GeneratePointerIfNeeded(const coded::UnionType& union_type) {
265     if (union_type.referenced_by_pointer) {
266         Emit(&tables_file_, "static const banjo_type_t ");
267         Emit(&tables_file_, NameTable(union_type.pointer_name));
268         Emit(&tables_file_, " = banjo_type_t(::banjo::BanjoCodedUnionPointer(&");
269         Emit(&tables_file_, NameTable(union_type.coded_name));
270         Emit(&tables_file_, ".coded_union));\n");
271     }
272 }
273 
GenerateForward(const coded::StructType & struct_type)274 void TablesGenerator::GenerateForward(const coded::StructType& struct_type) {
275     Emit(&tables_file_, "extern const banjo_type_t ");
276     Emit(&tables_file_, NameTable(struct_type.coded_name));
277     Emit(&tables_file_, ";\n");
278 }
279 
GenerateForward(const coded::UnionType & union_type)280 void TablesGenerator::GenerateForward(const coded::UnionType& union_type) {
281     Emit(&tables_file_, "extern const banjo_type_t ");
282     Emit(&tables_file_, NameTable(union_type.coded_name));
283     Emit(&tables_file_, ";\n");
284 }
285 
CompileType(const flat::Type * type)286 const coded::Type* TablesGenerator::CompileType(const flat::Type* type) {
287     switch (type->kind) {
288     case flat::Type::Kind::kArray: {
289         auto array_type = static_cast<const flat::ArrayType*>(type);
290         auto iter = array_type_map_.find(array_type);
291         if (iter != array_type_map_.end())
292             return iter->second;
293         auto coded_element_type = CompileType(array_type->element_type.get());
294         uint32_t array_size = array_type->size;
295         uint32_t element_size = array_type->element_type->size;
296         auto name = NameCodedArray(coded_element_type->coded_name, array_size);
297         auto coded_array_type = std::make_unique<coded::ArrayType>(
298             std::move(name), coded_element_type, array_size, element_size);
299         array_type_map_[array_type] = coded_array_type.get();
300         coded_types_.push_back(std::move(coded_array_type));
301         return coded_types_.back().get();
302     }
303     case flat::Type::Kind::kVector: {
304         auto vector_type = static_cast<const flat::VectorType*>(type);
305         auto iter = vector_type_map_.find(vector_type);
306         if (iter != vector_type_map_.end())
307             return iter->second;
308         auto coded_element_type = CompileType(vector_type->element_type.get());
309         uint32_t max_count = vector_type->element_count.Value();
310         uint32_t element_size = coded_element_type->size;
311         StringView element_name = coded_element_type->coded_name;
312         auto name = NameCodedVector(element_name, max_count, vector_type->nullability);
313         auto coded_vector_type = std::make_unique<coded::VectorType>(
314             std::move(name), coded_element_type, max_count, element_size, vector_type->nullability);
315         vector_type_map_[vector_type] = coded_vector_type.get();
316         coded_types_.push_back(std::move(coded_vector_type));
317         return coded_types_.back().get();
318     }
319     case flat::Type::Kind::kString: {
320         auto string_type = static_cast<const flat::StringType*>(type);
321         auto iter = string_type_map_.find(string_type);
322         if (iter != string_type_map_.end())
323             return iter->second;
324         uint32_t max_size = string_type->max_size.Value();
325         auto name = NameCodedString(max_size, string_type->nullability);
326         auto coded_string_type = std::make_unique<coded::StringType>(std::move(name), max_size,
327                                                                      string_type->nullability);
328         string_type_map_[string_type] = coded_string_type.get();
329         coded_types_.push_back(std::move(coded_string_type));
330         return coded_types_.back().get();
331     }
332     case flat::Type::Kind::kHandle: {
333         auto handle_type = static_cast<const flat::HandleType*>(type);
334         auto iter = handle_type_map_.find(handle_type);
335         if (iter != handle_type_map_.end())
336             return iter->second;
337         auto name = NameCodedHandle(handle_type->subtype, handle_type->nullability);
338         auto coded_handle_type = std::make_unique<coded::HandleType>(
339             std::move(name), handle_type->subtype, handle_type->nullability);
340         handle_type_map_[handle_type] = coded_handle_type.get();
341         coded_types_.push_back(std::move(coded_handle_type));
342         return coded_types_.back().get();
343     }
344     case flat::Type::Kind::kRequestHandle: {
345         auto request_type = static_cast<const flat::RequestHandleType*>(type);
346         auto iter = request_type_map_.find(request_type);
347         if (iter != request_type_map_.end())
348             return iter->second;
349         auto name = NameCodedRequestHandle(NameName(request_type->name, "_", "_"), request_type->nullability);
350         auto coded_request_type =
351             std::make_unique<coded::RequestHandleType>(std::move(name), request_type->nullability);
352         request_type_map_[request_type] = coded_request_type.get();
353         coded_types_.push_back(std::move(coded_request_type));
354         return coded_types_.back().get();
355     }
356     case flat::Type::Kind::kPrimitive: {
357         auto primitive_type = static_cast<const flat::PrimitiveType*>(type);
358         auto iter = primitive_type_map_.find(primitive_type);
359         if (iter != primitive_type_map_.end())
360             return iter->second;
361         auto name = NamePrimitiveSubtype(primitive_type->subtype);
362         auto coded_primitive_type = std::make_unique<coded::PrimitiveType>(
363             std::move(name), primitive_type->subtype,
364             flat::PrimitiveType::SubtypeSize(primitive_type->subtype));
365         primitive_type_map_[primitive_type] = coded_primitive_type.get();
366         coded_types_.push_back(std::move(coded_primitive_type));
367         return coded_types_.back().get();
368     }
369     case flat::Type::Kind::kIdentifier: {
370         auto identifier_type = static_cast<const flat::IdentifierType*>(type);
371         auto iter = named_coded_types_.find(&identifier_type->name);
372         if (iter == named_coded_types_.end()) {
373             assert(false && "unknown type in named type map!");
374         }
375         // We may need to set the emit-pointer bit on structs and unions now.
376         auto coded_type = iter->second.get();
377         switch (coded_type->kind) {
378         case coded::Type::Kind::kStruct: {
379             // Structs were compiled as part of decl compilation,
380             // but we may now need to generate the StructPointer.
381             if (identifier_type->nullability != types::Nullability::kNullable)
382                 break;
383             auto coded_struct_type = static_cast<coded::StructType*>(coded_type);
384             coded_struct_type->referenced_by_pointer = true;
385             coded_types_.push_back(std::make_unique<coded::StructPointerType>(
386                 coded_struct_type->pointer_name, coded_struct_type));
387             return coded_types_.back().get();
388         }
389         case coded::Type::Kind::kUnion: {
390             // Unions were compiled as part of decl compilation,
391             // but we may now need to generate the UnionPointer.
392             if (identifier_type->nullability != types::Nullability::kNullable)
393                 break;
394             auto coded_union_type = static_cast<coded::UnionType*>(coded_type);
395             coded_union_type->referenced_by_pointer = true;
396             coded_types_.push_back(std::make_unique<coded::UnionPointerType>(
397                 coded_union_type->pointer_name, coded_union_type));
398             return coded_types_.back().get();
399         }
400         case coded::Type::Kind::kInterface: {
401             auto iter = interface_type_map_.find(identifier_type);
402             if (iter != interface_type_map_.end())
403                 return iter->second;
404             auto name = NameCodedInterfaceHandle(NameName(identifier_type->name, "_", "_"),
405                                                  identifier_type->nullability);
406             auto coded_interface_type = std::make_unique<coded::InterfaceHandleType>(
407                 std::move(name), identifier_type->nullability);
408             interface_type_map_[identifier_type] = coded_interface_type.get();
409             coded_types_.push_back(std::move(coded_interface_type));
410             return coded_types_.back().get();
411         }
412         case coded::Type::Kind::kPrimitive:
413             // These are from enums. We don't need to do anything with them.
414             break;
415         case coded::Type::Kind::kInterfaceHandle:
416         case coded::Type::Kind::kStructPointer:
417         case coded::Type::Kind::kUnionPointer:
418         case coded::Type::Kind::kMessage:
419         case coded::Type::Kind::kRequestHandle:
420         case coded::Type::Kind::kHandle:
421         case coded::Type::Kind::kArray:
422         case coded::Type::Kind::kVector:
423         case coded::Type::Kind::kString:
424             assert(false && "anonymous type in named type map!");
425             break;
426         }
427         return coded_type;
428     }
429     }
430 }
431 
CompileFields(const flat::Decl * decl)432 void TablesGenerator::CompileFields(const flat::Decl* decl) {
433     switch (decl->kind) {
434     case flat::Decl::Kind::kInterface: {
435         auto interface_decl = static_cast<const flat::Interface*>(decl);
436         coded::InterfaceType* coded_interface =
437             static_cast<coded::InterfaceType*>(named_coded_types_[&decl->name].get());
438         size_t i = 0;
439         for (const auto& method_pointer : interface_decl->all_methods) {
440             assert(method_pointer != nullptr);
441             const auto& method = *method_pointer;
442             auto CompileMessage = [&](const flat::Interface::Method::Message& message) -> void {
443                 std::unique_ptr<coded::MessageType>& coded_message = coded_interface->messages[i++];
444                 std::vector<coded::StructField>& request_fields = coded_message->fields;
445                 for (const auto& parameter : message.parameters) {
446                     std::string parameter_name =
447                         coded_message->coded_name + "_" + std::string(parameter.name.data());
448                     auto coded_parameter_type = CompileType(parameter.type.get());
449                     if (coded_parameter_type->coding_needed == coded::CodingNeeded::kNeeded)
450                         request_fields.emplace_back(coded_parameter_type,
451                                                     parameter.fieldshape.Offset());
452                 }
453                 // We move the coded_message to coded_types_ so that we'll generate tables for the
454                 // message
455                 // in the proper order.
456                 coded_types_.push_back(std::move(coded_message));
457             };
458             if (method.maybe_request) {
459                 CompileMessage(*method.maybe_request);
460             }
461             if (method.maybe_response) {
462                 CompileMessage(*method.maybe_response);
463             }
464         }
465         break;
466     }
467     case flat::Decl::Kind::kStruct: {
468         auto struct_decl = static_cast<const flat::Struct*>(decl);
469         coded::StructType* coded_struct =
470             static_cast<coded::StructType*>(named_coded_types_[&decl->name].get());
471         std::vector<coded::StructField>& struct_fields = coded_struct->fields;
472         for (const auto& member : struct_decl->members) {
473             std::string member_name =
474                 coded_struct->coded_name + "_" + std::string(member.name.data());
475             auto coded_member_type = CompileType(member.type.get());
476             if (coded_member_type->coding_needed == coded::CodingNeeded::kNeeded)
477                 struct_fields.emplace_back(coded_member_type, member.fieldshape.Offset());
478         }
479         break;
480     }
481     case flat::Decl::Kind::kUnion: {
482         auto union_decl = static_cast<const flat::Union*>(decl);
483         coded::UnionType* union_struct =
484             static_cast<coded::UnionType*>(named_coded_types_[&decl->name].get());
485         std::vector<const coded::Type*>& union_members = union_struct->types;
486         for (const auto& member : union_decl->members) {
487             std::string member_name =
488                 union_struct->coded_name + "_" + std::string(member.name.data());
489             auto coded_member_type = CompileType(member.type.get());
490             if (coded_member_type->coding_needed == coded::CodingNeeded::kNeeded) {
491                 union_members.push_back(coded_member_type);
492             } else {
493                 // We need union_members.size() to match union_decl->members.size() because
494                 // the coding tables will use the union |tag| to index into the member array.
495                 union_members.push_back(nullptr);
496             }
497         }
498         break;
499     }
500     default: { break; }
501     }
502 }
503 
Compile(const flat::Decl * decl)504 void TablesGenerator::Compile(const flat::Decl* decl) {
505     switch (decl->kind) {
506     case flat::Decl::Kind::kConst:
507         // Nothing to do for const declarations.
508         break;
509     case flat::Decl::Kind::kEnum: {
510         auto enum_decl = static_cast<const flat::Enum*>(decl);
511         std::string enum_name = NameName(enum_decl->name, "_", "_");
512         named_coded_types_.emplace(&enum_decl->name,
513                                    std::make_unique<coded::PrimitiveType>(
514                                        std::move(enum_name), enum_decl->type,
515                                        flat::PrimitiveType::SubtypeSize(enum_decl->type)));
516         break;
517     }
518     case flat::Decl::Kind::kInterface: {
519         auto interface_decl = static_cast<const flat::Interface*>(decl);
520         std::string interface_name = NameInterface(*interface_decl);
521         std::string interface_qname = NameName(interface_decl->name, ".", "/");
522         std::vector<std::unique_ptr<coded::MessageType>> interface_messages;
523         for (const auto& method_pointer : interface_decl->all_methods) {
524             assert(method_pointer != nullptr);
525             const auto& method = *method_pointer;
526             std::string method_name = NameMethod(interface_name, method);
527             std::string method_qname = NameMethod(interface_qname, method);
528             auto CreateMessage = [&](const flat::Interface::Method::Message& message,
529                                      types::MessageKind kind) -> void {
530                 std::string message_name = NameMessage(method_name, kind);
531                 std::string message_qname = NameMessage(method_qname, kind);
532                 interface_messages.push_back(std::make_unique<coded::MessageType>(
533                     std::move(message_name), std::vector<coded::StructField>(),
534                     message.typeshape.Size(), std::move(message_qname)));
535             };
536             if (method.maybe_request) {
537                 CreateMessage(*method.maybe_request, types::MessageKind::kRequest);
538             }
539             if (method.maybe_response) {
540                 auto kind = method.maybe_request ? types::MessageKind::kResponse
541                                                  : types::MessageKind::kEvent;
542                 CreateMessage(*method.maybe_response, kind);
543             }
544         }
545         named_coded_types_.emplace(
546             &decl->name, std::make_unique<coded::InterfaceType>(std::move(interface_messages)));
547         break;
548     }
549     case flat::Decl::Kind::kStruct: {
550         auto struct_decl = static_cast<const flat::Struct*>(decl);
551         std::string struct_name = NameCodedStruct(struct_decl);
552         std::string pointer_name = NamePointer(struct_name);
553         named_coded_types_.emplace(
554             &decl->name,
555             std::make_unique<coded::StructType>(std::move(struct_name), std::vector<coded::StructField>(),
556                                                 struct_decl->typeshape.Size(),
557                                                 std::move(pointer_name), NameName(struct_decl->name, ".", "/")));
558         break;
559     }
560     case flat::Decl::Kind::kUnion: {
561         auto union_decl = static_cast<const flat::Union*>(decl);
562         std::string union_name = NameCodedUnion(union_decl);
563         std::string pointer_name = NamePointer(union_name);
564         named_coded_types_.emplace(
565             &decl->name, std::make_unique<coded::UnionType>(
566                              std::move(union_name), std::vector<const coded::Type*>(),
567                              union_decl->membershape.Offset(), union_decl->typeshape.Size(),
568                              std::move(pointer_name), NameName(union_decl->name, ".", "/")));
569         break;
570     }
571     }
572 }
573 
Produce()574 std::ostringstream TablesGenerator::Produce() {
575     GenerateFilePreamble();
576 
577     for (const auto& decl : library_->declaration_order_) {
578         Compile(decl);
579     }
580 
581     for (const auto& decl : library_->declaration_order_) {
582         if (decl->name.library() != library_)
583             continue;
584         CompileFields(decl);
585     }
586 
587     for (const auto& decl : library_->declaration_order_) {
588         coded::Type* coded_type = named_coded_types_[&decl->name].get();
589         if (!coded_type)
590             continue;
591         switch (coded_type->kind) {
592         case coded::Type::Kind::kStruct:
593             GenerateForward(*static_cast<const coded::StructType*>(coded_type));
594             break;
595         case coded::Type::Kind::kUnion:
596             GenerateForward(*static_cast<const coded::UnionType*>(coded_type));
597             break;
598         default:
599             break;
600         }
601     }
602 
603     Emit(&tables_file_, "\n");
604 
605     for (const auto& decl : library_->declaration_order_) {
606         coded::Type* coded_type = named_coded_types_[&decl->name].get();
607         if (!coded_type)
608             continue;
609         switch (coded_type->kind) {
610         case coded::Type::Kind::kStruct:
611             GeneratePointerIfNeeded(*static_cast<const coded::StructType*>(coded_type));
612             break;
613         case coded::Type::Kind::kUnion:
614             GeneratePointerIfNeeded(*static_cast<const coded::UnionType*>(coded_type));
615             break;
616         default:
617             break;
618         }
619     }
620 
621     Emit(&tables_file_, "\n");
622 
623     for (const auto& coded_type : coded_types_) {
624         if (coded_type->coding_needed == coded::CodingNeeded::kNotNeeded)
625             continue;
626 
627         switch (coded_type->kind) {
628         case coded::Type::Kind::kStruct:
629         case coded::Type::Kind::kStructPointer:
630         case coded::Type::Kind::kUnion:
631         case coded::Type::Kind::kUnionPointer:
632             // These are generated in the next phase.
633             break;
634         case coded::Type::Kind::kInterface:
635             // Nothing to generate for interfaces. We've already moved the
636             // messages from the interface into coded_types_ directly.
637             break;
638         case coded::Type::Kind::kMessage:
639             Generate(*static_cast<const coded::MessageType*>(coded_type.get()));
640             break;
641         case coded::Type::Kind::kHandle:
642             Generate(*static_cast<const coded::HandleType*>(coded_type.get()));
643             break;
644         case coded::Type::Kind::kInterfaceHandle:
645             Generate(*static_cast<const coded::InterfaceHandleType*>(coded_type.get()));
646             break;
647         case coded::Type::Kind::kRequestHandle:
648             Generate(*static_cast<const coded::RequestHandleType*>(coded_type.get()));
649             break;
650         case coded::Type::Kind::kArray:
651             Generate(*static_cast<const coded::ArrayType*>(coded_type.get()));
652             break;
653         case coded::Type::Kind::kString:
654             Generate(*static_cast<const coded::StringType*>(coded_type.get()));
655             break;
656         case coded::Type::Kind::kVector:
657             Generate(*static_cast<const coded::VectorType*>(coded_type.get()));
658             break;
659         case coded::Type::Kind::kPrimitive:
660             // These are only around to provide size information to
661             // vectors. There's never anything to generate, and this
662             // should not be reached.
663             assert(false && "Primitive types should never need coding tables");
664             break;
665         }
666     }
667 
668     for (const auto& decl : library_->declaration_order_) {
669         if (decl->name.library() != library_)
670             continue;
671 
672         coded::Type* coded_type = named_coded_types_[&decl->name].get();
673         if (!coded_type)
674             continue;
675         switch (coded_type->kind) {
676         case coded::Type::Kind::kStruct:
677             Generate(*static_cast<const coded::StructType*>(coded_type));
678             break;
679         case coded::Type::Kind::kUnion:
680             Generate(*static_cast<const coded::UnionType*>(coded_type));
681             break;
682         default:
683             continue;
684         }
685     }
686 
687     GenerateFilePostamble();
688 
689     return std::move(tables_file_);
690 }
691 
692 } // namespace banjo
693