1061da546Spatrick //===- LLDBPropertyDefEmitter.cpp -----------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick // These tablegen backends emits LLDB's PropertyDefinition values.
10061da546Spatrick //
11061da546Spatrick //===----------------------------------------------------------------------===//
12061da546Spatrick
13061da546Spatrick #include "LLDBTableGenBackends.h"
14061da546Spatrick #include "LLDBTableGenUtils.h"
15061da546Spatrick #include "llvm/ADT/StringExtras.h"
16061da546Spatrick #include "llvm/TableGen/Record.h"
17061da546Spatrick #include "llvm/TableGen/StringMatcher.h"
18061da546Spatrick #include "llvm/TableGen/TableGenBackend.h"
19061da546Spatrick #include <vector>
20061da546Spatrick
21061da546Spatrick using namespace llvm;
22061da546Spatrick using namespace lldb_private;
23061da546Spatrick
emitPropertyEnum(Record * Property,raw_ostream & OS)24061da546Spatrick static void emitPropertyEnum(Record *Property, raw_ostream &OS) {
25061da546Spatrick OS << "eProperty";
26061da546Spatrick OS << Property->getName();
27061da546Spatrick OS << ",\n";
28061da546Spatrick }
29061da546Spatrick
emitProperty(Record * Property,raw_ostream & OS)30061da546Spatrick static void emitProperty(Record *Property, raw_ostream &OS) {
31061da546Spatrick OS << " {";
32061da546Spatrick
33061da546Spatrick // Emit the property name.
34061da546Spatrick OS << "\"" << Property->getValueAsString("Name") << "\"";
35061da546Spatrick OS << ", ";
36061da546Spatrick
37061da546Spatrick // Emit the property type.
38*dda28197Spatrick llvm::StringRef type = Property->getValueAsString("Type");
39061da546Spatrick OS << "OptionValue::eType";
40*dda28197Spatrick OS << type;
41061da546Spatrick OS << ", ";
42061da546Spatrick
43061da546Spatrick // Emit the property's global value.
44061da546Spatrick OS << (Property->getValue("Global") ? "true" : "false");
45061da546Spatrick OS << ", ";
46061da546Spatrick
47061da546Spatrick bool hasDefaultUnsignedValue = Property->getValue("HasDefaultUnsignedValue");
48061da546Spatrick bool hasDefaultEnumValue = Property->getValue("HasDefaultEnumValue");
49061da546Spatrick bool hasDefaultStringValue = Property->getValue("HasDefaultStringValue");
50*dda28197Spatrick bool hasElementType = Property->getValue("HasElementType");
51061da546Spatrick
52061da546Spatrick // Guarantee that every property has a default value.
53061da546Spatrick assert((hasDefaultUnsignedValue || hasDefaultEnumValue ||
54*dda28197Spatrick hasDefaultStringValue || hasElementType) &&
55*dda28197Spatrick "Property must have a default value or an element type");
56061da546Spatrick
57061da546Spatrick // Guarantee that no property has both a default unsigned value and a default
58061da546Spatrick // enum value, since they're bothed stored in the same field.
59061da546Spatrick assert(!(hasDefaultUnsignedValue && hasDefaultEnumValue) &&
60061da546Spatrick "Property cannot have both a unsigned and enum default value.");
61061da546Spatrick
62061da546Spatrick // Guarantee that every boolean property has a boolean default value.
63061da546Spatrick assert(!(Property->getValueAsString("Type") == "Boolean" &&
64061da546Spatrick !Property->getValue("HasDefaultBooleanValue")) &&
65061da546Spatrick "Boolean property must have a boolean default value.");
66061da546Spatrick
67061da546Spatrick // Guarantee that every string property has a string default value.
68061da546Spatrick assert(!(Property->getValueAsString("Type") == "String" &&
69061da546Spatrick !hasDefaultStringValue) &&
70061da546Spatrick "String property must have a string default value.");
71061da546Spatrick
72061da546Spatrick // Guarantee that every enum property has an enum default value.
73061da546Spatrick assert(
74061da546Spatrick !(Property->getValueAsString("Type") == "Enum" && !hasDefaultEnumValue) &&
75061da546Spatrick "Enum property must have a enum default value.");
76061da546Spatrick
77*dda28197Spatrick // Guarantee that only arrays and dictionaries have an element type;
78*dda28197Spatrick assert(((type != "Array" && type != "Dictionary") || hasElementType) &&
79*dda28197Spatrick "Only dictionaries and arrays can have an element type.");
80*dda28197Spatrick
81061da546Spatrick // Emit the default uint value.
82061da546Spatrick if (hasDefaultUnsignedValue) {
83061da546Spatrick OS << std::to_string(Property->getValueAsInt("DefaultUnsignedValue"));
84061da546Spatrick } else if (hasDefaultEnumValue) {
85061da546Spatrick OS << Property->getValueAsString("DefaultEnumValue");
86*dda28197Spatrick } else if (hasElementType) {
87*dda28197Spatrick OS << "OptionValue::eType";
88*dda28197Spatrick OS << Property->getValueAsString("ElementType");
89061da546Spatrick } else {
90061da546Spatrick OS << "0";
91061da546Spatrick }
92061da546Spatrick OS << ", ";
93061da546Spatrick
94061da546Spatrick // Emit the default string value.
95061da546Spatrick if (hasDefaultStringValue) {
96061da546Spatrick if (auto D = Property->getValue("DefaultStringValue")) {
97061da546Spatrick OS << "\"";
98061da546Spatrick OS << D->getValue()->getAsUnquotedString();
99061da546Spatrick OS << "\"";
100061da546Spatrick } else {
101061da546Spatrick OS << "\"\"";
102061da546Spatrick }
103061da546Spatrick } else {
104061da546Spatrick OS << "nullptr";
105061da546Spatrick }
106061da546Spatrick OS << ", ";
107061da546Spatrick
108061da546Spatrick // Emit the enum values value.
109061da546Spatrick if (Property->getValue("EnumValues"))
110061da546Spatrick OS << Property->getValueAsString("EnumValues");
111061da546Spatrick else
112061da546Spatrick OS << "{}";
113061da546Spatrick OS << ", ";
114061da546Spatrick
115061da546Spatrick // Emit the property description.
116061da546Spatrick if (auto D = Property->getValue("Description")) {
117061da546Spatrick OS << "\"";
118061da546Spatrick OS << D->getValue()->getAsUnquotedString();
119061da546Spatrick OS << "\"";
120061da546Spatrick } else {
121061da546Spatrick OS << "\"\"";
122061da546Spatrick }
123061da546Spatrick
124061da546Spatrick OS << "},\n";
125061da546Spatrick }
126061da546Spatrick
127061da546Spatrick /// Emits all property initializers to the raw_ostream.
emityProperties(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)128061da546Spatrick static void emityProperties(std::string PropertyName,
129061da546Spatrick std::vector<Record *> PropertyRecords,
130061da546Spatrick raw_ostream &OS) {
131061da546Spatrick // Generate the macro that the user needs to define before including the
132061da546Spatrick // *.inc file.
133061da546Spatrick std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
134061da546Spatrick std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
135061da546Spatrick
136061da546Spatrick // All options are in one file, so we need put them behind macros and ask the
137061da546Spatrick // user to define the macro for the options that are needed.
138061da546Spatrick OS << "// Property definitions for " << PropertyName << "\n";
139061da546Spatrick OS << "#ifdef " << NeededMacro << "\n";
140061da546Spatrick OS << "static constexpr PropertyDefinition g_" << PropertyName
141061da546Spatrick << "_properties[] = {\n";
142061da546Spatrick for (Record *R : PropertyRecords)
143061da546Spatrick emitProperty(R, OS);
144061da546Spatrick OS << "};\n";
145061da546Spatrick // We undefine the macro for the user like Clang's include files are doing it.
146061da546Spatrick OS << "#undef " << NeededMacro << "\n";
147061da546Spatrick OS << "#endif // " << PropertyName << " Property\n\n";
148061da546Spatrick }
149061da546Spatrick
150061da546Spatrick /// Emits all property initializers to the raw_ostream.
emitPropertyEnum(std::string PropertyName,std::vector<Record * > PropertyRecords,raw_ostream & OS)151061da546Spatrick static void emitPropertyEnum(std::string PropertyName,
152061da546Spatrick std::vector<Record *> PropertyRecords,
153061da546Spatrick raw_ostream &OS) {
154061da546Spatrick // Generate the macro that the user needs to define before including the
155061da546Spatrick // *.inc file.
156061da546Spatrick std::string NeededMacro = "LLDB_PROPERTIES_" + PropertyName;
157061da546Spatrick std::replace(NeededMacro.begin(), NeededMacro.end(), ' ', '_');
158061da546Spatrick
159061da546Spatrick // All options are in one file, so we need put them behind macros and ask the
160061da546Spatrick // user to define the macro for the options that are needed.
161061da546Spatrick OS << "// Property enum cases for " << PropertyName << "\n";
162061da546Spatrick OS << "#ifdef " << NeededMacro << "\n";
163061da546Spatrick for (Record *R : PropertyRecords)
164061da546Spatrick emitPropertyEnum(R, OS);
165061da546Spatrick // We undefine the macro for the user like Clang's include files are doing it.
166061da546Spatrick OS << "#undef " << NeededMacro << "\n";
167061da546Spatrick OS << "#endif // " << PropertyName << " Property\n\n";
168061da546Spatrick }
169061da546Spatrick
EmitPropertyDefs(RecordKeeper & Records,raw_ostream & OS)170061da546Spatrick void lldb_private::EmitPropertyDefs(RecordKeeper &Records, raw_ostream &OS) {
171061da546Spatrick emitSourceFileHeader("Property definitions for LLDB.", OS);
172061da546Spatrick
173061da546Spatrick std::vector<Record *> Properties =
174061da546Spatrick Records.getAllDerivedDefinitions("Property");
175061da546Spatrick for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
176061da546Spatrick emityProperties(PropertyRecordPair.first, PropertyRecordPair.second, OS);
177061da546Spatrick }
178061da546Spatrick }
179061da546Spatrick
EmitPropertyEnumDefs(RecordKeeper & Records,raw_ostream & OS)180061da546Spatrick void lldb_private::EmitPropertyEnumDefs(RecordKeeper &Records,
181061da546Spatrick raw_ostream &OS) {
182061da546Spatrick emitSourceFileHeader("Property definition enum for LLDB.", OS);
183061da546Spatrick
184061da546Spatrick std::vector<Record *> Properties =
185061da546Spatrick Records.getAllDerivedDefinitions("Property");
186061da546Spatrick for (auto &PropertyRecordPair : getRecordsByName(Properties, "Definition")) {
187061da546Spatrick emitPropertyEnum(PropertyRecordPair.first, PropertyRecordPair.second, OS);
188061da546Spatrick }
189061da546Spatrick }
190