1971f9ca6SJonas Devlieghere //===- LLDBPropertyDefEmitter.cpp -----------------------------------------===//
2971f9ca6SJonas Devlieghere //
3971f9ca6SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4971f9ca6SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
5971f9ca6SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6971f9ca6SJonas Devlieghere //
7971f9ca6SJonas Devlieghere //===----------------------------------------------------------------------===//
8971f9ca6SJonas Devlieghere //
9971f9ca6SJonas Devlieghere // These tablegen backends emits LLDB's PropertyDefinition values.
10971f9ca6SJonas Devlieghere //
11971f9ca6SJonas Devlieghere //===----------------------------------------------------------------------===//
12971f9ca6SJonas Devlieghere
13971f9ca6SJonas Devlieghere #include "LLDBTableGenBackends.h"
14be019c7aSJonas Devlieghere #include "LLDBTableGenUtils.h"
15971f9ca6SJonas Devlieghere #include "llvm/ADT/StringExtras.h"
16971f9ca6SJonas Devlieghere #include "llvm/TableGen/Record.h"
17971f9ca6SJonas Devlieghere #include "llvm/TableGen/StringMatcher.h"
18971f9ca6SJonas Devlieghere #include "llvm/TableGen/TableGenBackend.h"
19971f9ca6SJonas Devlieghere #include <vector>
20971f9ca6SJonas Devlieghere
21971f9ca6SJonas Devlieghere using namespace llvm;
22310f6b89SJonas Devlieghere using namespace lldb_private;
23971f9ca6SJonas Devlieghere
emitPropertyEnum(Record * Property,raw_ostream & OS)24971f9ca6SJonas Devlieghere static void emitPropertyEnum(Record *Property, raw_ostream &OS) {
25971f9ca6SJonas Devlieghere OS << "eProperty";
26971f9ca6SJonas Devlieghere OS << Property->getName();
27971f9ca6SJonas Devlieghere OS << ",\n";
28971f9ca6SJonas Devlieghere }
29971f9ca6SJonas Devlieghere
emitProperty(Record * Property,raw_ostream & OS)30971f9ca6SJonas Devlieghere static void emitProperty(Record *Property, raw_ostream &OS) {
31971f9ca6SJonas Devlieghere OS << " {";
32971f9ca6SJonas Devlieghere
33971f9ca6SJonas Devlieghere // Emit the property name.
34971f9ca6SJonas Devlieghere OS << "\"" << Property->getValueAsString("Name") << "\"";
35971f9ca6SJonas Devlieghere OS << ", ";
36971f9ca6SJonas Devlieghere
37971f9ca6SJonas Devlieghere // Emit the property type.
38*09c8845aSJonas Devlieghere llvm::StringRef type = Property->getValueAsString("Type");
39971f9ca6SJonas Devlieghere OS << "OptionValue::eType";
40*09c8845aSJonas Devlieghere OS << type;
41971f9ca6SJonas Devlieghere OS << ", ";
42971f9ca6SJonas Devlieghere
43971f9ca6SJonas Devlieghere // Emit the property's global value.
44971f9ca6SJonas Devlieghere OS << (Property->getValue("Global") ? "true" : "false");
45971f9ca6SJonas Devlieghere OS << ", ";
46971f9ca6SJonas Devlieghere
47971f9ca6SJonas Devlieghere bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue");
48971f9ca6SJonas Devlieghere bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue");
49971f9ca6SJonas Devlieghere bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue");
50*09c8845aSJonas Devlieghere bool hasElementType = Property->getValue("HasElementType");
51971f9ca6SJonas Devlieghere
52971f9ca6SJonas Devlieghere // Guarantee that every property has a default value.
53971f9ca6SJonas Devlieghere assert((hasDefaultUnsignedValue || hasDefaultEnumValue ||
54*09c8845aSJonas Devlieghere hasDefaultStringValue || hasElementType) &&
55*09c8845aSJonas Devlieghere "Property must have a default value or an element type");
56971f9ca6SJonas Devlieghere
57971f9ca6SJonas Devlieghere // Guarantee that no property has both a default unsigned value and a default
58971f9ca6SJonas Devlieghere // enum value, since they're bothed stored in the same field.
59971f9ca6SJonas Devlieghere assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) &&
60971f9ca6SJonas Devlieghere "Property cannot have both a unsigned and enum default value.");
61971f9ca6SJonas Devlieghere
625934cd11SJonas Devlieghere // Guarantee that every boolean property has a boolean default value.
635934cd11SJonas Devlieghere assert(!(Property->getValueAsString("Type") == "Boolean" &&
6410b5cd8eSJonas Devlieghere !Property->getValue("HasDefaultBooleanValue")) &&
655934cd11SJonas Devlieghere "Boolean property must have a boolean default value.");
665934cd11SJonas Devlieghere
675934cd11SJonas Devlieghere // Guarantee that every string property has a string default value.
685934cd11SJonas Devlieghere assert(!(Property->getValueAsString("Type") == "String" &&
695934cd11SJonas Devlieghere !hasDefaultStringValue) &&
705934cd11SJonas Devlieghere "String property must have a string default value.");
715934cd11SJonas Devlieghere
725934cd11SJonas Devlieghere // Guarantee that every enum property has an enum default value.
735934cd11SJonas Devlieghere assert(
745934cd11SJonas Devlieghere !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) &&
755934cd11SJonas Devlieghere "Enum property must have a enum default value.");
765934cd11SJonas Devlieghere
77*09c8845aSJonas Devlieghere // Guarantee that only arrays and dictionaries have an element type;
78*09c8845aSJonas Devlieghere assert(((type != "Array" && type != "Dictionary") || hasElementType) &&
79*09c8845aSJonas Devlieghere "Only dictionaries and arrays can have an element type.");
80*09c8845aSJonas Devlieghere
81971f9ca6SJonas Devlieghere // Emit the default uint value.
82971f9ca6SJonas Devlieghere if (hasDefaultUnsignedValue) {
83971f9ca6SJonas Devlieghere OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue"));
84971f9ca6SJonas Devlieghere } else if (hasDefaultEnumValue) {
85971f9ca6SJonas Devlieghere OS << Property->getValueAsString("DefaultEnumValue");
86*09c8845aSJonas Devlieghere } else if (hasElementType) {
87*09c8845aSJonas Devlieghere OS << "OptionValue::eType";
88*09c8845aSJonas Devlieghere OS << Property->getValueAsString("ElementType");
89971f9ca6SJonas Devlieghere } else {
90971f9ca6SJonas Devlieghere OS << "0";
91971f9ca6SJonas Devlieghere }
92971f9ca6SJonas Devlieghere OS << ", ";
93971f9ca6SJonas Devlieghere
94971f9ca6SJonas Devlieghere // Emit the default string value.
95971f9ca6SJonas Devlieghere if (hasDefaultStringValue) {
96971f9ca6SJonas Devlieghere if (auto D = Property->getValue("DefaultStringValue")) {
97971f9ca6SJonas Devlieghere OS << "\"";
987296fac5SJonas Devlieghere OS << D->getValue()->getAsUnquotedString();
99971f9ca6SJonas Devlieghere OS << "\"";
100971f9ca6SJonas Devlieghere } else {
101971f9ca6SJonas Devlieghere OS << "\"\"";
102971f9ca6SJonas Devlieghere }
103971f9ca6SJonas Devlieghere } else {
104971f9ca6SJonas Devlieghere OS << "nullptr";
105971f9ca6SJonas Devlieghere }
106971f9ca6SJonas Devlieghere OS << ", ";
107971f9ca6SJonas Devlieghere
108971f9ca6SJonas Devlieghere // Emit the enum values value.
109971f9ca6SJonas Devlieghere if (Property->getValue("EnumValues"))
110971f9ca6SJonas Devlieghere OS << Property->getValueAsString("EnumValues");
111971f9ca6SJonas Devlieghere else
112971f9ca6SJonas Devlieghere OS << "{}";
113971f9ca6SJonas Devlieghere OS << ", ";
114971f9ca6SJonas Devlieghere
115971f9ca6SJonas Devlieghere // Emit the property description.
116971f9ca6SJonas Devlieghere if (auto D = Property->getValue("Description")) {
117971f9ca6SJonas Devlieghere OS << "\"";
1187296fac5SJonas Devlieghere OS << D->getValue()->getAsUnquotedString();
119971f9ca6SJonas Devlieghere OS << "\"";
120971f9ca6SJonas Devlieghere } else {
121971f9ca6SJonas Devlieghere OS << "\"\"";
122971f9ca6SJonas Devlieghere }
123971f9ca6SJonas Devlieghere
124971f9ca6SJonas Devlieghere OS << "},\n";
125971f9ca6SJonas Devlieghere }
126971f9ca6SJonas Devlieghere
127971f9ca6SJonas Devlieghere /// Emits all property initializers to the raw_ostream.
emityProperties(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)128971f9ca6SJonas Devlieghere static void emityProperties(std::string PropertyName,
129971f9ca6SJonas Devlieghere std::vector<Record *> PropertyRecords,
130971f9ca6SJonas Devlieghere raw_ostream &OS) {
131971f9ca6SJonas Devlieghere // Generate the macro that the user needs to define before including the
132971f9ca6SJonas Devlieghere // *.inc file.
133971f9ca6SJonas Devlieghere std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
134971f9ca6SJonas Devlieghere std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
135971f9ca6SJonas Devlieghere
136971f9ca6SJonas Devlieghere // All options are in one file, so we need put them behind macros and ask the
137971f9ca6SJonas Devlieghere // user to define the macro for the options that are needed.
138971f9ca6SJonas Devlieghere OS << "// Property definitions for " << PropertyName << "\n";
139971f9ca6SJonas Devlieghere OS << "#ifdef " << NeededMacro << "\n";
140a8ea5955SJonas Devlieghere OS << "static constexpr PropertyDefinition g_" << PropertyName
141a8ea5955SJonas Devlieghere << "_properties[] = {\n";
142971f9ca6SJonas Devlieghere for (Record *R : PropertyRecords)
143971f9ca6SJonas Devlieghere emitProperty(R, OS);
144a8ea5955SJonas Devlieghere OS << "};\n";
145971f9ca6SJonas Devlieghere // We undefine the macro for the user like Clang's include files are doing it.
146971f9ca6SJonas Devlieghere OS << "#undef " << NeededMacro << "\n";
147971f9ca6SJonas Devlieghere OS << "#endif // " << PropertyName << " Property\n\n";
148971f9ca6SJonas Devlieghere }
149971f9ca6SJonas Devlieghere
150971f9ca6SJonas Devlieghere /// Emits all property initializers to the raw_ostream.
emitPropertyEnum(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)151971f9ca6SJonas Devlieghere static void emitPropertyEnum(std::string PropertyName,
152971f9ca6SJonas Devlieghere std::vector<Record *> PropertyRecords,
153971f9ca6SJonas Devlieghere raw_ostream &OS) {
154971f9ca6SJonas Devlieghere // Generate the macro that the user needs to define before including the
155971f9ca6SJonas Devlieghere // *.inc file.
156971f9ca6SJonas Devlieghere std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
157971f9ca6SJonas Devlieghere std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
158971f9ca6SJonas Devlieghere
159971f9ca6SJonas Devlieghere // All options are in one file, so we need put them behind macros and ask the
160971f9ca6SJonas Devlieghere // user to define the macro for the options that are needed.
161971f9ca6SJonas Devlieghere OS << "// Property enum cases for " << PropertyName << "\n";
162971f9ca6SJonas Devlieghere OS << "#ifdef " << NeededMacro << "\n";
163971f9ca6SJonas Devlieghere for (Record *R : PropertyRecords)
164971f9ca6SJonas Devlieghere emitPropertyEnum(R, OS);
165971f9ca6SJonas Devlieghere // We undefine the macro for the user like Clang's include files are doing it.
166971f9ca6SJonas Devlieghere OS << "#undef " << NeededMacro << "\n";
167971f9ca6SJonas Devlieghere OS << "#endif // " << PropertyName << " Property\n\n";
168971f9ca6SJonas Devlieghere }
169971f9ca6SJonas Devlieghere
EmitPropertyDefs(RecordKeeper & Records,raw_ostream & OS)170971f9ca6SJonas Devlieghere void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) {
171971f9ca6SJonas Devlieghere emitSourceFileHeader("Property definitions for LLDB.", OS);
172971f9ca6SJonas Devlieghere
173971f9ca6SJonas Devlieghere std::vector<Record *> Properties =
174971f9ca6SJonas Devlieghere Records.getAllDerivedDefinitions("Property");
175be019c7aSJonas Devlieghere for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
176971f9ca6SJonas Devlieghere emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS);
177971f9ca6SJonas Devlieghere }
178971f9ca6SJonas Devlieghere }
179971f9ca6SJonas Devlieghere
EmitPropertyEnumDefs(RecordKeeper & Records,raw_ostream & OS)180971f9ca6SJonas Devlieghere void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records,
181971f9ca6SJonas Devlieghere raw_ostream &OS) {
182971f9ca6SJonas Devlieghere emitSourceFileHeader("Property definition enum for LLDB.", OS);
183971f9ca6SJonas Devlieghere
184971f9ca6SJonas Devlieghere std::vector<Record *> Properties =
185971f9ca6SJonas Devlieghere Records.getAllDerivedDefinitions("Property");
186be019c7aSJonas Devlieghere for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
187971f9ca6SJonas Devlieghere emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS);
188971f9ca6SJonas Devlieghere }
189971f9ca6SJonas Devlieghere }
190