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