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