================
@@ -605,3 +607,188 @@ void clang::EmitClangBuiltins(const RecordKeeper
&Records, raw_ostream &OS) {
#undef ATOMIC_BUILTIN
)c++";
}
+
+//===----------------------------------------------------------------------===//
+// Builtin documentation emitter
+//===----------------------------------------------------------------------===//
+
+/// Holds the data needed to emit documentation for a single builtin.
+namespace {
+struct BuiltinDocData {
+ const Record *Documentation = nullptr;
+ const Record *BuiltinRecord = nullptr;
+ std::string Heading;
+};
+} // namespace
+
+static void writeCategoryHeader(const Record *Category, raw_ostream &OS) {
+ StringRef CategoryName = Category->getValueAsString("Name");
+ OS << "\n" << CategoryName << "\n";
+ for (size_t I = 0, E = CategoryName.size(); I < E; ++I)
+ OS << "=";
+ OS << "\n\n";
+
+ StringRef CategoryContent = Category->getValueAsString("Content");
+ if (!CategoryContent.trim().empty())
+ OS << CategoryContent.trim() << "\n\n";
+}
+
+/// Split a parameter list string into individual parameter type strings,
+/// respecting nested angle brackets (e.g. address_space<4>, _ExtVector<4,
+/// float>).
+static SmallVector<StringRef> splitParams(StringRef Params) {
+ SmallVector<StringRef> Result;
+ if (Params.empty())
+ return Result;
+
+ int Depth = 0;
+ size_t Start = 0;
+ for (size_t I = 0, E = Params.size(); I < E; ++I) {
+ if (Params[I] == '<') {
+ ++Depth;
+ } else if (Params[I] == '>') {
+ --Depth;
+ } else if (Params[I] == ',' && Depth == 0) {
+ Result.push_back(Params.substr(Start, I - Start).trim());
+ Start = I + 1;
+ }
+ }
+ // Add the last parameter.
+ StringRef Last = Params.substr(Start).trim();
+ if (!Last.empty())
+ Result.push_back(Last);
+ return Result;
+}
+
+static void writeBuiltinDocumentation(const BuiltinDocData &Doc,
+ raw_ostream &OS) {
+ // Write heading with '-' underline (subsection).
+ std::string HeadingText = "``" + Doc.Heading + "``";
+ OS << HeadingText << "\n";
+ for (size_t I = 0, E = HeadingText.size(); I < E; ++I)
+ OS << "-";
+ OS << "\n\n";
+
+ // Write prototype as a code block.
+ StringRef Prototype = Doc.BuiltinRecord->getValueAsString("Prototype");
+ if (!Prototype.empty()) {
+ std::vector<StringRef> Spellings =
+ Doc.BuiltinRecord->getValueAsListOfStrings("Spellings");
+ StringRef Name =
+ Spellings.empty() ? Doc.BuiltinRecord->getName() : Spellings[0];
+
+ // Split prototype into return type and params at the first '('.
+ size_t ParenPos = Prototype.find('(');
+ if (ParenPos != StringRef::npos) {
+ StringRef RetType = Prototype.substr(0, ParenPos).rtrim();
+ StringRef ParamStr =
+ Prototype.substr(ParenPos + 1, Prototype.size() - ParenPos - 2);
+
+ OS << "**Prototype:**\n\n";
+ OS << ".. code-block:: c\n\n";
+ OS << " " << RetType << " " << Name << "(";
+
+ std::vector<StringRef> ArgNames =
----------------
jhuber6 wrote:
Why do we use `SmallVector` in some places and `std::vector` in others?
https://github.com/llvm/llvm-project/pull/181573
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits