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