Skip to content

Commit 0166fde

Browse files
[libc][RFC] add support for function level attributes
1 parent 74bf0b1 commit 0166fde

File tree

3 files changed

+95
-5
lines changed

3 files changed

+95
-5
lines changed

libc/spec/spec.td

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,29 @@ class ArgSpec<Type type, list<Annotation> annotations = [], string name = ""> {
170170
string Name = name;
171171
}
172172

173-
class FunctionSpec<string name, RetValSpec return, list<ArgSpec> args> {
173+
class FunctionAttr {}
174+
class GnuFunctionAttr<string attr> : FunctionAttr {
175+
string Attr = attr;
176+
string Style = "gnu";
177+
}
178+
class C23FunctionAttr<string attr, string namespace> : FunctionAttr {
179+
string Attr = attr;
180+
string Namespace = namespace;
181+
string Style = "c23";
182+
}
183+
class DeclspecFunctionAttr<string attr> : FunctionAttr {
184+
string Attr = attr;
185+
string Style = "declspec";
186+
}
187+
class FunctionAttrSpec<list<FunctionAttr> instances> {
188+
list<FunctionAttr> Instances = instances;
189+
}
190+
191+
class FunctionSpec<string name, RetValSpec return, list<ArgSpec> args, list<FunctionAttrSpec> attrs = []> {
174192
string Name = name;
175193
RetValSpec Return = return;
176194
list<ArgSpec> Args = args;
195+
list<FunctionAttrSpec> Attributes = attrs;
177196
}
178197

179198
class ObjectSpec<string name, string type> {

libc/utils/HdrGen/PublicAPICommand.cpp

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/ADT/StringRef.h"
1616
#include "llvm/Support/SourceMgr.h"
1717
#include "llvm/TableGen/Record.h"
18+
#include <llvm/ADT/STLExtras.h>
1819

1920
// Text blocks for macro definitions and type decls can be indented to
2021
// suit the surrounding tablegen listing. We need to dedent such blocks
@@ -49,7 +50,7 @@ namespace llvm_libc {
4950

5051
void writeAPIFromIndex(APIIndexer &G,
5152
std::vector<std::string> EntrypointNameList,
52-
llvm::raw_ostream &OS) {
53+
llvm::raw_ostream &OS, AttributeStyle PreferedStyle) {
5354
for (auto &Pair : G.MacroDefsMap) {
5455
const std::string &Name = Pair.first;
5556
if (G.MacroSpecMap.find(Name) == G.MacroSpecMap.end())
@@ -102,6 +103,62 @@ void writeAPIFromIndex(APIIndexer &G,
102103
llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
103104
llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
104105

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+
}
161+
105162
OS << G.getTypeAsString(ReturnType) << " " << Name << "(";
106163

107164
auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
@@ -134,12 +191,24 @@ void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args,
134191
llvm::StringRef StdHeader,
135192
llvm::RecordKeeper &Records,
136193
const Command::ErrorReporter &Reporter) const {
137-
if (Args.size() != 0) {
138-
Reporter.printFatalError("public_api command does not take any arguments.");
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+
}
139208
}
140209

141210
APIIndexer G(StdHeader, Records);
142-
writeAPIFromIndex(G, EntrypointNameList, OS);
211+
writeAPIFromIndex(G, EntrypointNameList, OS, PreferedStyle);
143212
}
144213

145214
} // namespace llvm_libc

libc/utils/HdrGen/PublicAPICommand.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class RecordKeeper;
2525

2626
namespace llvm_libc {
2727

28+
enum class AttributeStyle { None, Gnu, C23, Declspec };
29+
2830
class PublicAPICommand : public Command {
2931
private:
3032
const std::vector<std::string> &EntrypointNameList;

0 commit comments

Comments
 (0)