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