15
15
#include " llvm/ADT/StringRef.h"
16
16
#include " llvm/Support/SourceMgr.h"
17
17
#include " llvm/TableGen/Record.h"
18
+ #include < algorithm>
18
19
#include < llvm/ADT/STLExtras.h>
19
20
20
21
// Text blocks for macro definitions and type decls can be indented to
@@ -50,7 +51,7 @@ namespace llvm_libc {
50
51
51
52
void writeAPIFromIndex (APIIndexer &G,
52
53
std::vector<std::string> EntrypointNameList,
53
- llvm::raw_ostream &OS, AttributeStyle PreferedStyle ) {
54
+ llvm::raw_ostream &OS) {
54
55
for (auto &Pair : G.MacroDefsMap ) {
55
56
const std::string &Name = Pair.first ;
56
57
if (G.MacroSpecMap .find (Name) == G.MacroSpecMap .end ())
@@ -88,6 +89,71 @@ void writeAPIFromIndex(APIIndexer &G,
88
89
if (G.Enumerations .size () != 0 )
89
90
OS << " };\n\n " ;
90
91
92
+ // declare macros for attributes
93
+ llvm::DenseMap<llvm::StringRef, llvm::Record *> MacroAttr;
94
+ for (auto &Name : EntrypointNameList) {
95
+ if (G.FunctionSpecMap .find (Name) == G.FunctionSpecMap .end ()) {
96
+ continue ;
97
+ }
98
+ llvm::Record *FunctionSpec = G.FunctionSpecMap [Name];
99
+ auto Attributes = FunctionSpec->getValueAsListOfDefs (" Attributes" );
100
+ for (auto *Attr : Attributes) {
101
+ MacroAttr[Attr->getValueAsString (" Macro" )] = Attr;
102
+ }
103
+ }
104
+
105
+ auto GetStyle = [](llvm::Record *Instance) {
106
+ auto Style = Instance->getValueAsString (" Style" );
107
+ if (Style == " cxx11" )
108
+ return AttributeStyle::Cxx11;
109
+ if (Style == " gnu" )
110
+ return AttributeStyle::Gnu;
111
+ return AttributeStyle::Declspec;
112
+ };
113
+
114
+ for (auto &[Macro, Attr] : MacroAttr) {
115
+ auto Instances = Attr->getValueAsListOfDefs (" Instances" );
116
+ llvm::SmallVector<std::pair<AttributeStyle, llvm::Record *>> Styles;
117
+ std::transform (Instances.begin (), Instances.end (),
118
+ std::back_inserter (Styles),
119
+ [&](llvm::Record *Instance)
120
+ -> std::pair<AttributeStyle, llvm::Record *> {
121
+ auto Style = GetStyle (Instance);
122
+ return {Style, Instance};
123
+ });
124
+ // Effectively sort on the first field
125
+ std::sort (Styles.begin (), Styles.end ());
126
+ for (auto &[Style, Instance] : Styles) {
127
+ if (Style == AttributeStyle::Cxx11) {
128
+ OS << " #if !defined(" << Macro << " ) && defined(__cplusplus)\n " ;
129
+ OS << " #define " << Macro << " [[" ;
130
+ auto Namespace = Instance->getValueAsString (" Namespace" );
131
+ if (Namespace != " " )
132
+ OS << Namespace << " ::" ;
133
+ OS << Instance->getValueAsString (" Attr" ) << " ]]\n " ;
134
+ OS << " #endif\n " ;
135
+ }
136
+ if (Style == AttributeStyle::Gnu) {
137
+ OS << " #if !defined(" << Macro << " ) && defined(__GNUC__)\n " ;
138
+ OS << " #define " << Macro << " __attribute__((" ;
139
+ OS << Instance->getValueAsString (" Attr" ) << " ))\n " ;
140
+ OS << " #endif\n " ;
141
+ }
142
+ if (Style == AttributeStyle::Declspec) {
143
+ OS << " #if !defined(" << Macro << " ) && defined(_MSC_VER)\n " ;
144
+ OS << " #define " << Macro << " __declspec(" ;
145
+ OS << Instance->getValueAsString (" Attr" ) << " )\n " ;
146
+ OS << " #endif\n " ;
147
+ }
148
+ }
149
+ OS << " #if !defined(" << Macro << " )\n " ;
150
+ OS << " #define " << Macro << ' \n ' ;
151
+ OS << " #endif\n " ;
152
+ }
153
+
154
+ if (!MacroAttr.empty ())
155
+ OS << ' \n ' ;
156
+
91
157
OS << " __BEGIN_C_DECLS\n\n " ;
92
158
for (auto &Name : EntrypointNameList) {
93
159
if (G.FunctionSpecMap .find (Name) == G.FunctionSpecMap .end ()) {
@@ -103,61 +169,13 @@ void writeAPIFromIndex(APIIndexer &G,
103
169
llvm::Record *RetValSpec = FunctionSpec->getValueAsDef (" Return" );
104
170
llvm::Record *ReturnType = RetValSpec->getValueAsDef (" ReturnType" );
105
171
106
- auto GetStyle = [](llvm::Record *Instance) {
107
- auto Style = Instance->getValueAsString (" Style" );
108
- if (Style == " gnu" )
109
- return AttributeStyle::Gnu;
110
- if (Style == " c23" )
111
- return AttributeStyle::C23;
112
- if (Style == " declspec" )
113
- return AttributeStyle::Declspec;
114
- return AttributeStyle::None;
115
- };
116
-
117
- if (PreferedStyle != AttributeStyle::None) {
118
- auto Attributes = FunctionSpec->getValueAsListOfDefs (" Attributes" );
119
- llvm::SmallVector<llvm::Record *> Attrs;
120
- for (auto *Attr : Attributes) {
121
- auto Instances = Attr->getValueAsListOfDefs (" Instances" );
122
- for (auto *Instance : Instances) {
123
- if (GetStyle (Instance) == PreferedStyle) {
124
- Attrs.push_back (Instance);
125
- }
126
- }
127
- }
128
-
129
- if (Attrs.size () != 0 ) {
130
- if (PreferedStyle == AttributeStyle::Gnu) {
131
- OS << " __attribute__((" ;
132
- llvm::interleaveComma (Attrs, OS, [&](llvm::Record *Instance) {
133
- OS << Instance->getValueAsString (" Attr" );
134
- });
135
- OS << " )) " ;
136
- }
137
-
138
- if (PreferedStyle == AttributeStyle::C23) {
139
- OS << " __attribute__((" ;
140
- llvm::interleaveComma (Attrs, OS, [&](llvm::Record *Instance) {
141
- auto Namespace = Instance->getValueAsString (" Namespace" );
142
- if (Namespace != " " )
143
- OS << Namespace << " ::" ;
144
- OS << Instance->getValueAsString (" Attr" );
145
- });
146
- OS << " )) " ;
147
- }
148
-
149
- if (PreferedStyle == AttributeStyle::Declspec) {
150
- OS << " __declspec(" ;
151
- llvm::interleave (
152
- Attrs.begin (), Attrs.end (),
153
- [&](llvm::Record *Instance) {
154
- OS << Instance->getValueAsString (" Attr" );
155
- },
156
- [&]() { OS << ' ' ; });
157
- OS << " ) " ;
158
- }
159
- }
160
- }
172
+ auto Attributes = FunctionSpec->getValueAsListOfDefs (" Attributes" );
173
+ llvm::interleave (
174
+ Attributes.begin (), Attributes.end (),
175
+ [&](llvm::Record *Attr) { OS << Attr->getValueAsString (" Macro" ); },
176
+ [&]() { OS << ' ' ; });
177
+ if (!Attributes.empty ())
178
+ OS << ' ' ;
161
179
162
180
OS << G.getTypeAsString (ReturnType) << " " << Name << " (" ;
163
181
@@ -181,6 +199,10 @@ void writeAPIFromIndex(APIIndexer &G,
181
199
OS << " extern " << Type << " " << Name << " ;\n " ;
182
200
}
183
201
OS << " __END_C_DECLS\n " ;
202
+
203
+ // undef the macros
204
+ for (auto &[Macro, Attr] : MacroAttr)
205
+ OS << " \n #undef " << Macro << ' \n ' ;
184
206
}
185
207
186
208
void writePublicAPI (llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {}
@@ -191,24 +213,12 @@ void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args,
191
213
llvm::StringRef StdHeader,
192
214
llvm::RecordKeeper &Records,
193
215
const Command::ErrorReporter &Reporter) const {
194
- if (Args.size () > 1 ) {
195
- Reporter.printFatalError (
196
- " public_api command does not take more than one arguments." );
197
- }
198
-
199
- AttributeStyle PreferedStyle = AttributeStyle::Gnu;
200
-
201
- for (auto &arg : Args) {
202
- if (arg == " prefer-c23-attributes" ) {
203
- PreferedStyle = AttributeStyle::C23;
204
- }
205
- if (arg == " prefer-no-attributes" ) {
206
- PreferedStyle = AttributeStyle::None;
207
- }
216
+ if (Args.size () != 0 ) {
217
+ Reporter.printFatalError (" public_api command does not take any arguments." );
208
218
}
209
219
210
220
APIIndexer G (StdHeader, Records);
211
- writeAPIFromIndex (G, EntrypointNameList, OS, PreferedStyle );
221
+ writeAPIFromIndex (G, EntrypointNameList, OS);
212
222
}
213
223
214
224
} // namespace llvm_libc
0 commit comments