================
@@ -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 =
----------------
shiltian wrote:

Good point. I'll update them to `SmallVector`.

https://github.com/llvm/llvm-project/pull/181573
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to