xref: /freebsd-src/contrib/llvm-project/lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
19dba64beSDimitry Andric //===- LLDBPropertyDefEmitter.cpp -----------------------------------------===//
29dba64beSDimitry Andric //
39dba64beSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49dba64beSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
59dba64beSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69dba64beSDimitry Andric //
79dba64beSDimitry Andric //===----------------------------------------------------------------------===//
89dba64beSDimitry Andric //
99dba64beSDimitry Andric // These tablegen backends emits LLDB's PropertyDefinition values.
109dba64beSDimitry Andric //
119dba64beSDimitry Andric //===----------------------------------------------------------------------===//
129dba64beSDimitry Andric 
139dba64beSDimitry Andric #include "LLDBTableGenBackends.h"
149dba64beSDimitry Andric #include "LLDBTableGenUtils.h"
159dba64beSDimitry Andric #include "llvm/ADT/StringExtras.h"
169dba64beSDimitry Andric #include "llvm/TableGen/Record.h"
179dba64beSDimitry Andric #include "llvm/TableGen/StringMatcher.h"
189dba64beSDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
199dba64beSDimitry Andric #include <vector>
209dba64beSDimitry Andric 
219dba64beSDimitry Andric using namespace llvm;
229dba64beSDimitry Andric using namespace lldb_private;
239dba64beSDimitry Andric 
emitPropertyEnum(Record * Property,raw_ostream & OS)249dba64beSDimitry Andric static void emitPropertyEnum(Record *Property, raw_ostream &OS) {
259dba64beSDimitry Andric   OS << "eProperty";
269dba64beSDimitry Andric   OS << Property->getName();
279dba64beSDimitry Andric   OS << ",\n";
289dba64beSDimitry Andric }
299dba64beSDimitry Andric 
emitProperty(Record * Property,raw_ostream & OS)309dba64beSDimitry Andric static void emitProperty(Record *Property, raw_ostream &OS) {
319dba64beSDimitry Andric   OS << "  {";
329dba64beSDimitry Andric 
339dba64beSDimitry Andric   // Emit the property name.
349dba64beSDimitry Andric   OS << "\"" << Property->getValueAsString("Name") << "\"";
359dba64beSDimitry Andric   OS << ", ";
369dba64beSDimitry Andric 
379dba64beSDimitry Andric   // Emit the property type.
385ffd83dbSDimitry Andric   llvm::StringRef type = Property->getValueAsString("Type");
399dba64beSDimitry Andric   OS << "OptionValue::eType";
405ffd83dbSDimitry Andric   OS << type;
419dba64beSDimitry Andric   OS << ", ";
429dba64beSDimitry Andric 
439dba64beSDimitry Andric   // Emit the property's global value.
449dba64beSDimitry Andric   OS << (Property->getValue("Global") ? "true" : "false");
459dba64beSDimitry Andric   OS << ", ";
469dba64beSDimitry Andric 
479dba64beSDimitry Andric   bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue");
489dba64beSDimitry Andric   bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue");
499dba64beSDimitry Andric   bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue");
505ffd83dbSDimitry Andric   bool hasElementType = Property->getValue("HasElementType");
519dba64beSDimitry Andric 
529dba64beSDimitry Andric   // Guarantee that every property has a default value.
539dba64beSDimitry Andric   assert((hasDefaultUnsignedValue || hasDefaultEnumValue ||
545ffd83dbSDimitry Andric           hasDefaultStringValue || hasElementType) &&
555ffd83dbSDimitry Andric          "Property must have a default value or an element type");
569dba64beSDimitry Andric 
579dba64beSDimitry Andric   // Guarantee that no property has both a default unsigned value and a default
589dba64beSDimitry Andric   // enum value, since they're bothed stored in the same field.
599dba64beSDimitry Andric   assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) &&
609dba64beSDimitry Andric          "Property cannot have both a unsigned and enum default value.");
619dba64beSDimitry Andric 
62480093f4SDimitry Andric   // Guarantee that every boolean property has a boolean default value.
63480093f4SDimitry Andric   assert(!(Property->getValueAsString("Type") == "Boolean" &&
64480093f4SDimitry Andric            !Property->getValue("HasDefaultBooleanValue")) &&
65480093f4SDimitry Andric          "Boolean property must have a boolean default value.");
66480093f4SDimitry Andric 
67480093f4SDimitry Andric   // Guarantee that every string property has a string default value.
68480093f4SDimitry Andric   assert(!(Property->getValueAsString("Type") == "String" &&
69480093f4SDimitry Andric            !hasDefaultStringValue) &&
70480093f4SDimitry Andric          "String property must have a string default value.");
71480093f4SDimitry Andric 
72480093f4SDimitry Andric   // Guarantee that every enum property has an enum default value.
73480093f4SDimitry Andric   assert(
74480093f4SDimitry Andric       !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) &&
75480093f4SDimitry Andric       "Enum property must have a enum default value.");
76480093f4SDimitry Andric 
775ffd83dbSDimitry Andric   // Guarantee that only arrays and dictionaries have an element type;
785ffd83dbSDimitry Andric   assert(((type != "Array" && type != "Dictionary") || hasElementType) &&
795ffd83dbSDimitry Andric          "Only dictionaries and arrays can have an element type.");
805ffd83dbSDimitry Andric 
819dba64beSDimitry Andric   // Emit the default uint value.
829dba64beSDimitry Andric   if (hasDefaultUnsignedValue) {
839dba64beSDimitry Andric     OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue"));
849dba64beSDimitry Andric   } else if (hasDefaultEnumValue) {
859dba64beSDimitry Andric     OS << Property->getValueAsString("DefaultEnumValue");
865ffd83dbSDimitry Andric   } else if (hasElementType) {
875ffd83dbSDimitry Andric     OS << "OptionValue::eType";
885ffd83dbSDimitry Andric     OS << Property->getValueAsString("ElementType");
899dba64beSDimitry Andric   } else {
909dba64beSDimitry Andric     OS << "0";
919dba64beSDimitry Andric   }
929dba64beSDimitry Andric   OS << ", ";
939dba64beSDimitry Andric 
949dba64beSDimitry Andric   // Emit the default string value.
959dba64beSDimitry Andric   if (hasDefaultStringValue) {
969dba64beSDimitry Andric     if (auto D = Property->getValue("DefaultStringValue")) {
979dba64beSDimitry Andric       OS << "\"";
989dba64beSDimitry Andric       OS << D->getValue()->getAsUnquotedString();
999dba64beSDimitry Andric       OS << "\"";
1009dba64beSDimitry Andric     } else {
1019dba64beSDimitry Andric       OS << "\"\"";
1029dba64beSDimitry Andric     }
1039dba64beSDimitry Andric   } else {
1049dba64beSDimitry Andric     OS << "nullptr";
1059dba64beSDimitry Andric   }
1069dba64beSDimitry Andric   OS << ", ";
1079dba64beSDimitry Andric 
1089dba64beSDimitry Andric   // Emit the enum values value.
1099dba64beSDimitry Andric   if (Property->getValue("EnumValues"))
1109dba64beSDimitry Andric     OS << Property->getValueAsString("EnumValues");
1119dba64beSDimitry Andric   else
1129dba64beSDimitry Andric     OS << "{}";
1139dba64beSDimitry Andric   OS << ", ";
1149dba64beSDimitry Andric 
1159dba64beSDimitry Andric   // Emit the property description.
1169dba64beSDimitry Andric   if (auto D = Property->getValue("Description")) {
1179dba64beSDimitry Andric     OS << "\"";
1189dba64beSDimitry Andric     OS << D->getValue()->getAsUnquotedString();
1199dba64beSDimitry Andric     OS << "\"";
1209dba64beSDimitry Andric   } else {
1219dba64beSDimitry Andric     OS << "\"\"";
1229dba64beSDimitry Andric   }
1239dba64beSDimitry Andric 
1249dba64beSDimitry Andric   OS << "},\n";
1259dba64beSDimitry Andric }
1269dba64beSDimitry Andric 
1279dba64beSDimitry Andric /// Emits all property initializers to the raw_ostream.
emityProperties(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)1289dba64beSDimitry Andric static void emityProperties(std::string PropertyName,
1299dba64beSDimitry Andric                             std::vector<Record *> PropertyRecords,
1309dba64beSDimitry Andric                             raw_ostream &OS) {
1319dba64beSDimitry Andric   // Generate the macro that the user needs to define before including the
1329dba64beSDimitry Andric   // *.inc file.
1339dba64beSDimitry Andric   std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
1349dba64beSDimitry Andric   std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
1359dba64beSDimitry Andric 
1369dba64beSDimitry Andric   // All options are in one file, so we need put them behind macros and ask the
1379dba64beSDimitry Andric   // user to define the macro for the options that are needed.
1389dba64beSDimitry Andric   OS << "// Property definitions for " << PropertyName << "\n";
1399dba64beSDimitry Andric   OS << "#ifdef " << NeededMacro << "\n";
1409dba64beSDimitry Andric   OS << "static constexpr PropertyDefinition g_" << PropertyName
1419dba64beSDimitry Andric      << "_properties[] = {\n";
1429dba64beSDimitry Andric   for (Record *R : PropertyRecords)
1439dba64beSDimitry Andric     emitProperty(R, OS);
1449dba64beSDimitry Andric   OS << "};\n";
1459dba64beSDimitry Andric   // We undefine the macro for the user like Clang's include files are doing it.
1469dba64beSDimitry Andric   OS << "#undef " << NeededMacro << "\n";
1479dba64beSDimitry Andric   OS << "#endif // " << PropertyName << " Property\n\n";
1489dba64beSDimitry Andric }
1499dba64beSDimitry Andric 
1509dba64beSDimitry Andric /// Emits all property initializers to the raw_ostream.
emitPropertyEnum(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)1519dba64beSDimitry Andric static void emitPropertyEnum(std::string PropertyName,
1529dba64beSDimitry Andric                              std::vector<Record *> PropertyRecords,
1539dba64beSDimitry Andric                              raw_ostream &OS) {
1549dba64beSDimitry Andric   // Generate the macro that the user needs to define before including the
1559dba64beSDimitry Andric   // *.inc file.
1569dba64beSDimitry Andric   std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
1579dba64beSDimitry Andric   std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
1589dba64beSDimitry Andric 
1599dba64beSDimitry Andric   // All options are in one file, so we need put them behind macros and ask the
1609dba64beSDimitry Andric   // user to define the macro for the options that are needed.
1619dba64beSDimitry Andric   OS << "// Property enum cases for " << PropertyName << "\n";
1629dba64beSDimitry Andric   OS << "#ifdef " << NeededMacro << "\n";
1639dba64beSDimitry Andric   for (Record *R : PropertyRecords)
1649dba64beSDimitry Andric     emitPropertyEnum(R, OS);
1659dba64beSDimitry Andric   // We undefine the macro for the user like Clang's include files are doing it.
1669dba64beSDimitry Andric   OS << "#undef " << NeededMacro << "\n";
1679dba64beSDimitry Andric   OS << "#endif // " << PropertyName << " Property\n\n";
1689dba64beSDimitry Andric }
1699dba64beSDimitry Andric 
EmitPropertyDefs(RecordKeeper & Records,raw_ostream & OS)1709dba64beSDimitry Andric void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) {
171*5f757f3fSDimitry Andric   emitSourceFileHeader("Property definitions for LLDB.", OS, Records);
1729dba64beSDimitry Andric 
1739dba64beSDimitry Andric   std::vector<Record *> Properties =
1749dba64beSDimitry Andric       Records.getAllDerivedDefinitions("Property");
1759dba64beSDimitry Andric   for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
1769dba64beSDimitry Andric     emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS);
1779dba64beSDimitry Andric   }
1789dba64beSDimitry Andric }
1799dba64beSDimitry Andric 
EmitPropertyEnumDefs(RecordKeeper & Records,raw_ostream & OS)1809dba64beSDimitry Andric void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records,
1819dba64beSDimitry Andric                                         raw_ostream &OS) {
182*5f757f3fSDimitry Andric   emitSourceFileHeader("Property definition enum for LLDB.", OS, Records);
1839dba64beSDimitry Andric 
1849dba64beSDimitry Andric   std::vector<Record *> Properties =
1859dba64beSDimitry Andric       Records.getAllDerivedDefinitions("Property");
1869dba64beSDimitry Andric   for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
1879dba64beSDimitry Andric     emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS);
1889dba64beSDimitry Andric   }
1899dba64beSDimitry Andric }
190