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