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