1//===- offload-tblgen/DocGen.cpp - Tablegen backend for Offload header ----===//
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// This is a Tablegen backend that produces the contents of the Offload API
10// specification. The generated reStructuredText is Sphinx compatible, see
11// https://www.sphinx-doc.org/en/master/usage/domains/c.html for further
12// details on the C language domain.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/ADT/StringExtras.h"
17#include "llvm/Support/FormatVariadic.h"
18#include "llvm/TableGen/Record.h"
19#include "llvm/TableGen/TableGenBackend.h"
20
21#include "GenCommon.hpp"
22#include "RecordTypes.hpp"
23
24using namespace llvm;
25using namespace offload::tblgen;
26
27namespace {
28std::string makeFunctionSignature(StringRef RetTy, StringRef Name,
29 ArrayRef<ParamRec> Params) {
30 std::string S;
31 raw_string_ostream OS{S};
32 OS << RetTy << " " << Name << "(";
33 for (const ParamRec &Param : Params) {
34 OS << Param.getType() << " " << Param.getName();
35 if (Param != Params.back()) {
36 OS << ", ";
37 }
38 }
39 OS << ")";
40 return S;
41}
42
43std::string makeDoubleBackticks(StringRef R) {
44 std::string S;
45 for (char C : R) {
46 if (C == '`') {
47 S.push_back(c: '`');
48 }
49 S.push_back(c: C);
50 }
51 return S;
52}
53
54void processMacro(const MacroRec &M, raw_ostream &OS) {
55 OS << formatv(Fmt: ".. c:macro:: {0}\n\n", Vals: M.getNameWithArgs());
56 OS << " " << M.getDesc() << "\n\n";
57}
58
59void processTypedef(const TypedefRec &T, raw_ostream &OS) {
60 OS << formatv(Fmt: ".. c:type:: {0} {1}\n\n", Vals: T.getValue(), Vals: T.getName());
61 OS << " " << T.getDesc() << "\n\n";
62}
63
64void processHandle(const HandleRec &H, raw_ostream &OS) {
65
66 OS << formatv(Fmt: ".. c:type:: struct {0} *{1}\n\n", Vals: getHandleImplName(H),
67 Vals: H.getName());
68 OS << " " << H.getDesc() << "\n\n";
69}
70
71void processFptrTypedef(const FptrTypedefRec &F, raw_ostream &OS) {
72 OS << ".. c:type:: "
73 << makeFunctionSignature(RetTy: F.getReturn(),
74 Name: StringRef{formatv(Fmt: "(*{0})", Vals: F.getName())},
75 Params: F.getParams())
76 << "\n\n";
77 for (const ParamRec &P : F.getParams()) {
78 OS << formatv(Fmt: " :param {0}: {1}\n", Vals: P.getName(), Vals: P.getDesc());
79 }
80 OS << "\n";
81}
82
83void processEnum(const EnumRec &E, raw_ostream &OS) {
84 OS << formatv(Fmt: ".. c:enum:: {0}\n\n", Vals: E.getName());
85 OS << " " << E.getDesc() << "\n\n";
86 for (const EnumValueRec Etor : E.getValues()) {
87 OS << formatv(Fmt: " .. c:enumerator:: {0}_{1}\n\n", Vals: E.getEnumValNamePrefix(),
88 Vals: Etor.getName());
89 OS << " ";
90 if (E.isTyped()) {
91 OS << ":c:expr:`" << Etor.getTaggedType() << "` — ";
92 }
93 OS << Etor.getDesc() << "\n\n";
94 }
95}
96
97void processStruct(const StructRec &S, raw_ostream &OS) {
98 OS << formatv(Fmt: ".. c:struct:: {0}\n\n", Vals: S.getName());
99 OS << " " << S.getDesc() << "\n\n";
100 for (const StructMemberRec &M : S.getMembers()) {
101 OS << formatv(Fmt: " .. c:member:: {0} {1}\n\n", Vals: M.getType(), Vals: M.getName());
102 OS << " " << M.getDesc() << "\n\n";
103 }
104}
105
106void processFunction(const FunctionRec &F, raw_ostream &OS) {
107 OS << ".. c:function:: "
108 << makeFunctionSignature(RetTy: {formatv(Fmt: "{0}_result_t", Vals: PrefixLower)},
109 Name: F.getName(), Params: F.getParams())
110 << "\n\n";
111
112 OS << " " << F.getDesc() << "\n\n";
113 for (StringRef D : F.getDetails()) {
114 OS << " " << D << "\n";
115 }
116 if (!F.getDetails().empty()) {
117 OS << "\n";
118 }
119
120 for (const ParamRec &P : F.getParams()) {
121 OS << formatv(Fmt: " :param {0}: {1}\n", Vals: P.getName(), Vals: P.getDesc());
122 }
123
124 for (const ReturnRec &R : F.getReturns()) {
125 OS << formatv(Fmt: " :retval {0}:\n", Vals: R.getValue());
126 for (StringRef C : R.getConditions()) {
127 OS << " * ";
128 if (C.starts_with(Prefix: "`") && C.ends_with(Suffix: "`")) {
129 OS << ":c:expr:" << C;
130 } else {
131 OS << makeDoubleBackticks(R: C);
132 }
133 OS << "\n";
134 }
135 }
136 OS << "\n";
137}
138} // namespace
139
140void EmitOffloadDoc(const RecordKeeper &Records, raw_ostream &OS) {
141 OS << "Offload API\n";
142 OS << "===========\n\n";
143
144 ArrayRef<const Record *> Macros = Records.getAllDerivedDefinitions(ClassName: "Macro");
145 if (!Macros.empty()) {
146 OS << "Macros\n";
147 OS << "------\n\n";
148 for (const Record *M : Macros) {
149 processMacro(M: MacroRec{M}, OS);
150 }
151 }
152
153 ArrayRef<const Record *> Handles = Records.getAllDerivedDefinitions(ClassName: "Handle");
154 ArrayRef<const Record *> Typedefs =
155 Records.getAllDerivedDefinitions(ClassName: "Typedef");
156 ArrayRef<const Record *> FptrTypedefs =
157 Records.getAllDerivedDefinitions(ClassName: "FptrTypedef");
158 if (!Handles.empty() || !Typedefs.empty() || !FptrTypedefs.empty()) {
159 OS << "Type Definitions\n";
160 OS << "----------------\n\n";
161 for (const Record *H : Handles) {
162 processHandle(H: HandleRec{H}, OS);
163 }
164 for (const Record *T : Typedefs) {
165 processTypedef(T: TypedefRec{T}, OS);
166 }
167 for (const Record *F : FptrTypedefs) {
168 processFptrTypedef(F: FptrTypedefRec{F}, OS);
169 }
170 }
171
172 ArrayRef<const Record *> Enums = Records.getAllDerivedDefinitions(ClassName: "Enum");
173 OS << "Enums\n";
174 OS << "-----\n\n";
175 if (!Enums.empty()) {
176 for (const Record *E : Enums) {
177 processEnum(E: EnumRec{E}, OS);
178 }
179 }
180
181 ArrayRef<const Record *> Structs = Records.getAllDerivedDefinitions(ClassName: "Struct");
182 if (!Structs.empty()) {
183 OS << "Structs\n";
184 OS << "-------\n\n";
185 for (const Record *S : Structs) {
186 processStruct(S: StructRec{S}, OS);
187 }
188 }
189
190 ArrayRef<const Record *> Functions =
191 Records.getAllDerivedDefinitions(ClassName: "Function");
192 if (!Functions.empty()) {
193 OS << "Functions\n";
194 OS << "---------\n\n";
195 for (const Record *F : Functions) {
196 processFunction(F: FunctionRec{F}, OS);
197 }
198 }
199}
200

source code of offload/tools/offload-tblgen/DocGen.cpp