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