//===- LLDBPropertyDefEmitter.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // These tablegen backends emits LLDB's PropertyDefinition values. // //===----------------------------------------------------------------------===// #include "LLDBTableGenBackends.h" #include "LLDBTableGenUtils.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/TableGenBackend.h" #include using namespace llvm; using namespace lldb_private; static void emitPropertyEnum(Record *Property, raw_ostream &OS) { OS << "eProperty"; OS << Property->getName(); OS << ",\n"; } static void emitProperty(Record *Property, raw_ostream &OS) { OS << " {"; // Emit the property name. OS << "\"" << Property->getValueAsString("Name") << "\""; OS << ", "; // Emit the property type. llvm::StringRef type = Property->getValueAsString("Type"); OS << "OptionValue::eType"; OS << type; OS << ", "; // Emit the property's global value. OS << (Property->getValue("Global") ? "true" : "false"); OS << ", "; bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue"); bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue"); bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue"); bool hasElementType = Property->getValue("HasElementType"); // Guarantee that every property has a default value. assert((hasDefaultUnsignedValue || hasDefaultEnumValue || hasDefaultStringValue || hasElementType) && "Property must have a default value or an element type"); // Guarantee that no property has both a default unsigned value and a default // enum value, since they're bothed stored in the same field. assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) && "Property cannot have both a unsigned and enum default value."); // Guarantee that every boolean property has a boolean default value. assert(!(Property->getValueAsString("Type") == "Boolean" && !Property->getValue("HasDefaultBooleanValue")) && "Boolean property must have a boolean default value."); // Guarantee that every string property has a string default value. assert(!(Property->getValueAsString("Type") == "String" && !hasDefaultStringValue) && "String property must have a string default value."); // Guarantee that every enum property has an enum default value. assert( !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) && "Enum property must have a enum default value."); // Guarantee that only arrays and dictionaries have an element type; assert(((type != "Array" && type != "Dictionary") || hasElementType) && "Only dictionaries and arrays can have an element type."); // Emit the default uint value. if (hasDefaultUnsignedValue) { OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue")); } else if (hasDefaultEnumValue) { OS << Property->getValueAsString("DefaultEnumValue"); } else if (hasElementType) { OS << "OptionValue::eType"; OS << Property->getValueAsString("ElementType"); } else { OS << "0"; } OS << ", "; // Emit the default string value. if (hasDefaultStringValue) { if (auto D = Property->getValue("DefaultStringValue")) { OS << "\""; OS << D->getValue()->getAsUnquotedString(); OS << "\""; } else { OS << "\"\""; } } else { OS << "nullptr"; } OS << ", "; // Emit the enum values value. if (Property->getValue("EnumValues")) OS << Property->getValueAsString("EnumValues"); else OS << "{}"; OS << ", "; // Emit the property description. if (auto D = Property->getValue("Description")) { OS << "\""; OS << D->getValue()->getAsUnquotedString(); OS << "\""; } else { OS << "\"\""; } OS << "},\n"; } /// Emits all property initializers to the raw_ostream. static void emityProperties(std::string PropertyName, std::vector PropertyRecords, raw_ostream &OS) { // Generate the macro that the user needs to define before including the // *.inc file. std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName; std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_'); // All options are in one file, so we need put them behind macros and ask the // user to define the macro for the options that are needed. OS << "// Property definitions for " << PropertyName << "\n"; OS << "#ifdef " << NeededMacro << "\n"; OS << "static constexpr PropertyDefinition g_" << PropertyName << "_properties[] = {\n"; for (Record *R : PropertyRecords) emitProperty(R, OS); OS << "};\n"; // We undefine the macro for the user like Clang's include files are doing it. OS << "#undef " << NeededMacro << "\n"; OS << "#endif // " << PropertyName << " Property\n\n"; } /// Emits all property initializers to the raw_ostream. static void emitPropertyEnum(std::string PropertyName, std::vector PropertyRecords, raw_ostream &OS) { // Generate the macro that the user needs to define before including the // *.inc file. std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName; std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_'); // All options are in one file, so we need put them behind macros and ask the // user to define the macro for the options that are needed. OS << "// Property enum cases for " << PropertyName << "\n"; OS << "#ifdef " << NeededMacro << "\n"; for (Record *R : PropertyRecords) emitPropertyEnum(R, OS); // We undefine the macro for the user like Clang's include files are doing it. OS << "#undef " << NeededMacro << "\n"; OS << "#endif // " << PropertyName << " Property\n\n"; } void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Property definitions for LLDB.", OS, Records); std::vector Properties = Records.getAllDerivedDefinitions("Property"); for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) { emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS); } } void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Property definition enum for LLDB.", OS, Records); std::vector Properties = Records.getAllDerivedDefinitions("Property"); for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) { emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS); } }