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