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
emitPropertyEnum(Record * Property,raw_ostream & OS)24 static void emitPropertyEnum(Record *Property, raw_ostream &OS) {
25 OS << "eProperty";
26 OS << Property->getName();
27 OS << ",\n";
28 }
29
emitProperty(Record * Property,raw_ostream & OS)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 llvm::StringRef type = Property->getValueAsString("Type");
39 OS << "OptionValue::eType";
40 OS << type;
41 OS << ", ";
42
43 // Emit the property's global value.
44 OS << (Property->getValue("Global") ? "true" : "false");
45 OS << ", ";
46
47 bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue");
48 bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue");
49 bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue");
50 bool hasElementType = Property->getValue("HasElementType");
51
52 // Guarantee that every property has a default value.
53 assert((hasDefaultUnsignedValue || hasDefaultEnumValue ||
54 hasDefaultStringValue || hasElementType) &&
55 "Property must have a default value or an element type");
56
57 // Guarantee that no property has both a default unsigned value and a default
58 // enum value, since they're bothed stored in the same field.
59 assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) &&
60 "Property cannot have both a unsigned and enum default value.");
61
62 // Guarantee that every boolean property has a boolean default value.
63 assert(!(Property->getValueAsString("Type") == "Boolean" &&
64 !Property->getValue("HasDefaultBooleanValue")) &&
65 "Boolean property must have a boolean default value.");
66
67 // Guarantee that every string property has a string default value.
68 assert(!(Property->getValueAsString("Type") == "String" &&
69 !hasDefaultStringValue) &&
70 "String property must have a string default value.");
71
72 // Guarantee that every enum property has an enum default value.
73 assert(
74 !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) &&
75 "Enum property must have a enum default value.");
76
77 // Guarantee that only arrays and dictionaries have an element type;
78 assert(((type != "Array" && type != "Dictionary") || hasElementType) &&
79 "Only dictionaries and arrays can have an element type.");
80
81 // Emit the default uint value.
82 if (hasDefaultUnsignedValue) {
83 OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue"));
84 } else if (hasDefaultEnumValue) {
85 OS << Property->getValueAsString("DefaultEnumValue");
86 } else if (hasElementType) {
87 OS << "OptionValue::eType";
88 OS << Property->getValueAsString("ElementType");
89 } else {
90 OS << "0";
91 }
92 OS << ", ";
93
94 // Emit the default string value.
95 if (hasDefaultStringValue) {
96 if (auto D = Property->getValue("DefaultStringValue")) {
97 OS << "\"";
98 OS << D->getValue()->getAsUnquotedString();
99 OS << "\"";
100 } else {
101 OS << "\"\"";
102 }
103 } else {
104 OS << "nullptr";
105 }
106 OS << ", ";
107
108 // Emit the enum values value.
109 if (Property->getValue("EnumValues"))
110 OS << Property->getValueAsString("EnumValues");
111 else
112 OS << "{}";
113 OS << ", ";
114
115 // Emit the property description.
116 if (auto D = Property->getValue("Description")) {
117 OS << "\"";
118 OS << D->getValue()->getAsUnquotedString();
119 OS << "\"";
120 } else {
121 OS << "\"\"";
122 }
123
124 OS << "},\n";
125 }
126
127 /// Emits all property initializers to the raw_ostream.
emityProperties(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)128 static void emityProperties(std::string PropertyName,
129 std::vector<Record *> PropertyRecords,
130 raw_ostream &OS) {
131 // Generate the macro that the user needs to define before including the
132 // *.inc file.
133 std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
134 std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
135
136 // All options are in one file, so we need put them behind macros and ask the
137 // user to define the macro for the options that are needed.
138 OS << "// Property definitions for " << PropertyName << "\n";
139 OS << "#ifdef " << NeededMacro << "\n";
140 OS << "static constexpr PropertyDefinition g_" << PropertyName
141 << "_properties[] = {\n";
142 for (Record *R : PropertyRecords)
143 emitProperty(R, OS);
144 OS << "};\n";
145 // We undefine the macro for the user like Clang's include files are doing it.
146 OS << "#undef " << NeededMacro << "\n";
147 OS << "#endif // " << PropertyName << " Property\n\n";
148 }
149
150 /// Emits all property initializers to the raw_ostream.
emitPropertyEnum(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)151 static void emitPropertyEnum(std::string PropertyName,
152 std::vector<Record *> PropertyRecords,
153 raw_ostream &OS) {
154 // Generate the macro that the user needs to define before including the
155 // *.inc file.
156 std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
157 std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
158
159 // All options are in one file, so we need put them behind macros and ask the
160 // user to define the macro for the options that are needed.
161 OS << "// Property enum cases for " << PropertyName << "\n";
162 OS << "#ifdef " << NeededMacro << "\n";
163 for (Record *R : PropertyRecords)
164 emitPropertyEnum(R, OS);
165 // We undefine the macro for the user like Clang's include files are doing it.
166 OS << "#undef " << NeededMacro << "\n";
167 OS << "#endif // " << PropertyName << " Property\n\n";
168 }
169
EmitPropertyDefs(RecordKeeper & Records,raw_ostream & OS)170 void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) {
171 emitSourceFileHeader("Property definitions for LLDB.", OS);
172
173 std::vector<Record *> Properties =
174 Records.getAllDerivedDefinitions("Property");
175 for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
176 emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS);
177 }
178 }
179
EmitPropertyEnumDefs(RecordKeeper & Records,raw_ostream & OS)180 void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records,
181 raw_ostream &OS) {
182 emitSourceFileHeader("Property definition enum for LLDB.", OS);
183
184 std::vector<Record *> Properties =
185 Records.getAllDerivedDefinitions("Property");
186 for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
187 emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS);
188 }
189 }
190