1 //===- LLDBPropertyDefEmitter.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // These tablegen backends emits LLDB's PropertyDefinition values. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LLDBTableGenBackends.h" 14 #include "llvm/ADT/StringExtras.h" 15 #include "llvm/TableGen/Record.h" 16 #include "llvm/TableGen/StringMatcher.h" 17 #include "llvm/TableGen/TableGenBackend.h" 18 #include <map> 19 #include <vector> 20 21 using namespace llvm; 22 using namespace lldb_private; 23 24 /// Groups all properties by their definition. 25 static RecordsByName getPropertyList(std::vector<Record *> Properties) { 26 RecordsByName result; 27 for (Record *Property : Properties) 28 result[Property->getValueAsString("Definition").str()].push_back(Property); 29 return result; 30 } 31 32 static void emitPropertyEnum(Record *Property, raw_ostream &OS) { 33 OS << "eProperty"; 34 OS << Property->getName(); 35 OS << ",\n"; 36 } 37 38 static void emitProperty(Record *Property, raw_ostream &OS) { 39 OS << " {"; 40 41 // Emit the property name. 42 OS << "\"" << Property->getValueAsString("Name") << "\""; 43 OS << ", "; 44 45 // Emit the property type. 46 OS << "OptionValue::eType"; 47 OS << Property->getValueAsString("Type"); 48 OS << ", "; 49 50 // Emit the property's global value. 51 OS << (Property->getValue("Global") ? "true" : "false"); 52 OS << ", "; 53 54 bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue"); 55 bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue"); 56 bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue"); 57 58 // Guarantee that every property has a default value. 59 assert((hasDefaultUnsignedValue || hasDefaultEnumValue || 60 hasDefaultStringValue) && 61 "Property must have a default value"); 62 63 // Guarantee that no property has both a default unsigned value and a default 64 // enum value, since they're bothed stored in the same field. 65 assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) && 66 "Property cannot have both a unsigned and enum default value."); 67 68 // Emit the default uint value. 69 if (hasDefaultUnsignedValue) { 70 OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue")); 71 } else if (hasDefaultEnumValue) { 72 OS << Property->getValueAsString("DefaultEnumValue"); 73 } else { 74 OS << "0"; 75 } 76 OS << ", "; 77 78 // Emit the default string value. 79 if (hasDefaultStringValue) { 80 if (auto D = Property->getValue("DefaultStringValue")) { 81 OS << "\""; 82 OS << D->getValue()->getAsUnquotedString(); 83 OS << "\""; 84 } else { 85 OS << "\"\""; 86 } 87 } else { 88 OS << "nullptr"; 89 } 90 OS << ", "; 91 92 // Emit the enum values value. 93 if (Property->getValue("EnumValues")) 94 OS << Property->getValueAsString("EnumValues"); 95 else 96 OS << "{}"; 97 OS << ", "; 98 99 // Emit the property description. 100 if (auto D = Property->getValue("Description")) { 101 OS << "\""; 102 OS << D->getValue()->getAsUnquotedString(); 103 OS << "\""; 104 } else { 105 OS << "\"\""; 106 } 107 108 OS << "},\n"; 109 } 110 111 /// Emits all property initializers to the raw_ostream. 112 static void emityProperties(std::string PropertyName, 113 std::vector<Record *> PropertyRecords, 114 raw_ostream &OS) { 115 // Generate the macro that the user needs to define before including the 116 // *.inc file. 117 std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName; 118 std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_'); 119 120 // All options are in one file, so we need put them behind macros and ask the 121 // user to define the macro for the options that are needed. 122 OS << "// Property definitions for " << PropertyName << "\n"; 123 OS << "#ifdef " << NeededMacro << "\n"; 124 OS << "static constexpr PropertyDefinition g_" << PropertyName 125 << "_properties[] = {\n"; 126 for (Record *R : PropertyRecords) 127 emitProperty(R, OS); 128 OS << "};\n"; 129 // We undefine the macro for the user like Clang's include files are doing it. 130 OS << "#undef " << NeededMacro << "\n"; 131 OS << "#endif // " << PropertyName << " Property\n\n"; 132 } 133 134 /// Emits all property initializers to the raw_ostream. 135 static void emitPropertyEnum(std::string PropertyName, 136 std::vector<Record *> PropertyRecords, 137 raw_ostream &OS) { 138 // Generate the macro that the user needs to define before including the 139 // *.inc file. 140 std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName; 141 std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_'); 142 143 // All options are in one file, so we need put them behind macros and ask the 144 // user to define the macro for the options that are needed. 145 OS << "// Property enum cases for " << PropertyName << "\n"; 146 OS << "#ifdef " << NeededMacro << "\n"; 147 for (Record *R : PropertyRecords) 148 emitPropertyEnum(R, OS); 149 // We undefine the macro for the user like Clang's include files are doing it. 150 OS << "#undef " << NeededMacro << "\n"; 151 OS << "#endif // " << PropertyName << " Property\n\n"; 152 } 153 154 void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) { 155 emitSourceFileHeader("Property definitions for LLDB.", OS); 156 157 std::vector<Record *> Properties = 158 Records.getAllDerivedDefinitions("Property"); 159 for (auto &PropertyRecordPair : getPropertyList(Properties)) { 160 emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS); 161 } 162 } 163 164 void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records, 165 raw_ostream &OS) { 166 emitSourceFileHeader("Property definition enum for LLDB.", OS); 167 168 std::vector<Record *> Properties = 169 Records.getAllDerivedDefinitions("Property"); 170 for (auto &PropertyRecordPair : getPropertyList(Properties)) { 171 emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS); 172 } 173 } 174