xref: /freebsd-src/contrib/llvm-project/lldb/utils/TableGen/LLDBPropertyDefEmitter.cpp (revision 9dba64be9536c28e4800e06512b7f29b43ade345)
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