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 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 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. 389dba64beSDimitry Andric OS << "OptionValue::eType"; 399dba64beSDimitry Andric OS << Property->getValueAsString("Type"); 409dba64beSDimitry Andric OS << ", "; 419dba64beSDimitry Andric 429dba64beSDimitry Andric // Emit the property's global value. 439dba64beSDimitry Andric OS << (Property->getValue("Global") ? "true" : "false"); 449dba64beSDimitry Andric OS << ", "; 459dba64beSDimitry Andric 469dba64beSDimitry Andric bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue"); 479dba64beSDimitry Andric bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue"); 489dba64beSDimitry Andric bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue"); 499dba64beSDimitry Andric 509dba64beSDimitry Andric // Guarantee that every property has a default value. 519dba64beSDimitry Andric assert((hasDefaultUnsignedValue || hasDefaultEnumValue || 529dba64beSDimitry Andric hasDefaultStringValue) && 539dba64beSDimitry Andric "Property must have a default value"); 549dba64beSDimitry Andric 559dba64beSDimitry Andric // Guarantee that no property has both a default unsigned value and a default 569dba64beSDimitry Andric // enum value, since they're bothed stored in the same field. 579dba64beSDimitry Andric assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) && 589dba64beSDimitry Andric "Property cannot have both a unsigned and enum default value."); 599dba64beSDimitry Andric 60*480093f4SDimitry Andric // Guarantee that every boolean property has a boolean default value. 61*480093f4SDimitry Andric assert(!(Property->getValueAsString("Type") == "Boolean" && 62*480093f4SDimitry Andric !Property->getValue("HasDefaultBooleanValue")) && 63*480093f4SDimitry Andric "Boolean property must have a boolean default value."); 64*480093f4SDimitry Andric 65*480093f4SDimitry Andric // Guarantee that every string property has a string default value. 66*480093f4SDimitry Andric assert(!(Property->getValueAsString("Type") == "String" && 67*480093f4SDimitry Andric !hasDefaultStringValue) && 68*480093f4SDimitry Andric "String property must have a string default value."); 69*480093f4SDimitry Andric 70*480093f4SDimitry Andric // Guarantee that every enum property has an enum default value. 71*480093f4SDimitry Andric assert( 72*480093f4SDimitry Andric !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) && 73*480093f4SDimitry Andric "Enum property must have a enum default value."); 74*480093f4SDimitry Andric 759dba64beSDimitry Andric // Emit the default uint value. 769dba64beSDimitry Andric if (hasDefaultUnsignedValue) { 779dba64beSDimitry Andric OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue")); 789dba64beSDimitry Andric } else if (hasDefaultEnumValue) { 799dba64beSDimitry Andric OS << Property->getValueAsString("DefaultEnumValue"); 809dba64beSDimitry Andric } else { 819dba64beSDimitry Andric OS << "0"; 829dba64beSDimitry Andric } 839dba64beSDimitry Andric OS << ", "; 849dba64beSDimitry Andric 859dba64beSDimitry Andric // Emit the default string value. 869dba64beSDimitry Andric if (hasDefaultStringValue) { 879dba64beSDimitry Andric if (auto D = Property->getValue("DefaultStringValue")) { 889dba64beSDimitry Andric OS << "\""; 899dba64beSDimitry Andric OS << D->getValue()->getAsUnquotedString(); 909dba64beSDimitry Andric OS << "\""; 919dba64beSDimitry Andric } else { 929dba64beSDimitry Andric OS << "\"\""; 939dba64beSDimitry Andric } 949dba64beSDimitry Andric } else { 959dba64beSDimitry Andric OS << "nullptr"; 969dba64beSDimitry Andric } 979dba64beSDimitry Andric OS << ", "; 989dba64beSDimitry Andric 999dba64beSDimitry Andric // Emit the enum values value. 1009dba64beSDimitry Andric if (Property->getValue("EnumValues")) 1019dba64beSDimitry Andric OS << Property->getValueAsString("EnumValues"); 1029dba64beSDimitry Andric else 1039dba64beSDimitry Andric OS << "{}"; 1049dba64beSDimitry Andric OS << ", "; 1059dba64beSDimitry Andric 1069dba64beSDimitry Andric // Emit the property description. 1079dba64beSDimitry Andric if (auto D = Property->getValue("Description")) { 1089dba64beSDimitry Andric OS << "\""; 1099dba64beSDimitry Andric OS << D->getValue()->getAsUnquotedString(); 1109dba64beSDimitry Andric OS << "\""; 1119dba64beSDimitry Andric } else { 1129dba64beSDimitry Andric OS << "\"\""; 1139dba64beSDimitry Andric } 1149dba64beSDimitry Andric 1159dba64beSDimitry Andric OS << "},\n"; 1169dba64beSDimitry Andric } 1179dba64beSDimitry Andric 1189dba64beSDimitry Andric /// Emits all property initializers to the raw_ostream. 1199dba64beSDimitry Andric static void emityProperties(std::string PropertyName, 1209dba64beSDimitry Andric std::vector<Record *> PropertyRecords, 1219dba64beSDimitry Andric raw_ostream &OS) { 1229dba64beSDimitry Andric // Generate the macro that the user needs to define before including the 1239dba64beSDimitry Andric // *.inc file. 1249dba64beSDimitry Andric std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName; 1259dba64beSDimitry Andric std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_'); 1269dba64beSDimitry Andric 1279dba64beSDimitry Andric // All options are in one file, so we need put them behind macros and ask the 1289dba64beSDimitry Andric // user to define the macro for the options that are needed. 1299dba64beSDimitry Andric OS << "// Property definitions for " << PropertyName << "\n"; 1309dba64beSDimitry Andric OS << "#ifdef " << NeededMacro << "\n"; 1319dba64beSDimitry Andric OS << "static constexpr PropertyDefinition g_" << PropertyName 1329dba64beSDimitry Andric << "_properties[] = {\n"; 1339dba64beSDimitry Andric for (Record *R : PropertyRecords) 1349dba64beSDimitry Andric emitProperty(R, OS); 1359dba64beSDimitry Andric OS << "};\n"; 1369dba64beSDimitry Andric // We undefine the macro for the user like Clang's include files are doing it. 1379dba64beSDimitry Andric OS << "#undef " << NeededMacro << "\n"; 1389dba64beSDimitry Andric OS << "#endif // " << PropertyName << " Property\n\n"; 1399dba64beSDimitry Andric } 1409dba64beSDimitry Andric 1419dba64beSDimitry Andric /// Emits all property initializers to the raw_ostream. 1429dba64beSDimitry Andric static void emitPropertyEnum(std::string PropertyName, 1439dba64beSDimitry Andric std::vector<Record *> PropertyRecords, 1449dba64beSDimitry Andric raw_ostream &OS) { 1459dba64beSDimitry Andric // Generate the macro that the user needs to define before including the 1469dba64beSDimitry Andric // *.inc file. 1479dba64beSDimitry Andric std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName; 1489dba64beSDimitry Andric std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_'); 1499dba64beSDimitry Andric 1509dba64beSDimitry Andric // All options are in one file, so we need put them behind macros and ask the 1519dba64beSDimitry Andric // user to define the macro for the options that are needed. 1529dba64beSDimitry Andric OS << "// Property enum cases for " << PropertyName << "\n"; 1539dba64beSDimitry Andric OS << "#ifdef " << NeededMacro << "\n"; 1549dba64beSDimitry Andric for (Record *R : PropertyRecords) 1559dba64beSDimitry Andric emitPropertyEnum(R, OS); 1569dba64beSDimitry Andric // We undefine the macro for the user like Clang's include files are doing it. 1579dba64beSDimitry Andric OS << "#undef " << NeededMacro << "\n"; 1589dba64beSDimitry Andric OS << "#endif // " << PropertyName << " Property\n\n"; 1599dba64beSDimitry Andric } 1609dba64beSDimitry Andric 1619dba64beSDimitry Andric void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) { 1629dba64beSDimitry Andric emitSourceFileHeader("Property definitions for LLDB.", OS); 1639dba64beSDimitry Andric 1649dba64beSDimitry Andric std::vector<Record *> Properties = 1659dba64beSDimitry Andric Records.getAllDerivedDefinitions("Property"); 1669dba64beSDimitry Andric for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) { 1679dba64beSDimitry Andric emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS); 1689dba64beSDimitry Andric } 1699dba64beSDimitry Andric } 1709dba64beSDimitry Andric 1719dba64beSDimitry Andric void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records, 1729dba64beSDimitry Andric raw_ostream &OS) { 1739dba64beSDimitry Andric emitSourceFileHeader("Property definition enum for LLDB.", OS); 1749dba64beSDimitry Andric 1759dba64beSDimitry Andric std::vector<Record *> Properties = 1769dba64beSDimitry Andric Records.getAllDerivedDefinitions("Property"); 1779dba64beSDimitry Andric for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) { 1789dba64beSDimitry Andric emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS); 1799dba64beSDimitry Andric } 1809dba64beSDimitry Andric } 181