[libc-commits] [libc] Libc/attribute (PR #79891)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Mon Jan 29 12:06:08 PST 2024
https://github.com/SchrodingerZhu created https://github.com/llvm/llvm-project/pull/79891
None
>From c4fa940c4766011712196b93978066fb77665a9b Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Mon, 29 Jan 2024 14:21:25 -0500
Subject: [PATCH 1/2] [libc][RFC] add support for function level attributes
---
libc/spec/spec.td | 21 ++++++-
libc/utils/HdrGen/PublicAPICommand.cpp | 77 ++++++++++++++++++++++++--
libc/utils/HdrGen/PublicAPICommand.h | 2 +
3 files changed, 95 insertions(+), 5 deletions(-)
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 818cfaee6b61c2..f0493da57df7ed 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -169,10 +169,29 @@ class ArgSpec<Type type, list<Annotation> annotations = [], string name = ""> {
string Name = name;
}
-class FunctionSpec<string name, RetValSpec return, list<ArgSpec> args> {
+class FunctionAttr {}
+class GnuFunctionAttr<string attr> : FunctionAttr {
+ string Attr = attr;
+ string Style = "gnu";
+}
+class C23FunctionAttr<string attr, string namespace> : FunctionAttr {
+ string Attr = attr;
+ string Namespace = namespace;
+ string Style = "c23";
+}
+class DeclspecFunctionAttr<string attr> : FunctionAttr {
+ string Attr = attr;
+ string Style = "declspec";
+}
+class FunctionAttrSpec<list<FunctionAttr> instances> {
+ list<FunctionAttr> Instances = instances;
+}
+
+class FunctionSpec<string name, RetValSpec return, list<ArgSpec> args, list<FunctionAttrSpec> attrs = []> {
string Name = name;
RetValSpec Return = return;
list<ArgSpec> Args = args;
+ list<FunctionAttrSpec> Attributes = attrs;
}
class ObjectSpec<string name, string type> {
diff --git a/libc/utils/HdrGen/PublicAPICommand.cpp b/libc/utils/HdrGen/PublicAPICommand.cpp
index b1c7a072658ffb..26eb14c7589208 100644
--- a/libc/utils/HdrGen/PublicAPICommand.cpp
+++ b/libc/utils/HdrGen/PublicAPICommand.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Record.h"
+#include <llvm/ADT/STLExtras.h>
// Text blocks for macro definitions and type decls can be indented to
// suit the surrounding tablegen listing. We need to dedent such blocks
@@ -49,7 +50,7 @@ namespace llvm_libc {
void writeAPIFromIndex(APIIndexer &G,
std::vector<std::string> EntrypointNameList,
- llvm::raw_ostream &OS) {
+ llvm::raw_ostream &OS, AttributeStyle PreferedStyle) {
for (auto &Pair : G.MacroDefsMap) {
const std::string &Name = Pair.first;
if (G.MacroSpecMap.find(Name) == G.MacroSpecMap.end())
@@ -102,6 +103,62 @@ void writeAPIFromIndex(APIIndexer &G,
llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
+ auto GetStyle = [](llvm::Record *Instance) {
+ auto Style = Instance->getValueAsString("Style");
+ if (Style == "gnu")
+ return AttributeStyle::Gnu;
+ if (Style == "c23")
+ return AttributeStyle::C23;
+ if (Style == "declspec")
+ return AttributeStyle::Declspec;
+ return AttributeStyle::None;
+ };
+
+ if (PreferedStyle != AttributeStyle::None) {
+ auto Attributes = FunctionSpec->getValueAsListOfDefs("Attributes");
+ llvm::SmallVector<llvm::Record *> Attrs;
+ for (auto *Attr : Attributes) {
+ auto Instances = Attr->getValueAsListOfDefs("Instances");
+ for (auto *Instance : Instances) {
+ if (GetStyle(Instance) == PreferedStyle) {
+ Attrs.push_back(Instance);
+ }
+ }
+ }
+
+ if (Attrs.size() != 0) {
+ if (PreferedStyle == AttributeStyle::Gnu) {
+ OS << "__attribute__((";
+ llvm::interleaveComma(Attrs, OS, [&](llvm::Record *Instance) {
+ OS << Instance->getValueAsString("Attr");
+ });
+ OS << ")) ";
+ }
+
+ if (PreferedStyle == AttributeStyle::C23) {
+ OS << "__attribute__((";
+ llvm::interleaveComma(Attrs, OS, [&](llvm::Record *Instance) {
+ auto Namespace = Instance->getValueAsString("Namespace");
+ if (Namespace != "")
+ OS << Namespace << "::";
+ OS << Instance->getValueAsString("Attr");
+ });
+ OS << ")) ";
+ }
+
+ if (PreferedStyle == AttributeStyle::Declspec) {
+ OS << "__declspec(";
+ llvm::interleave(
+ Attrs.begin(), Attrs.end(),
+ [&](llvm::Record *Instance) {
+ OS << Instance->getValueAsString("Attr");
+ },
+ [&]() { OS << ' '; });
+ OS << ") ";
+ }
+ }
+ }
+
OS << G.getTypeAsString(ReturnType) << " " << Name << "(";
auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
@@ -134,12 +191,24 @@ void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader,
llvm::RecordKeeper &Records,
const Command::ErrorReporter &Reporter) const {
- if (Args.size() != 0) {
- Reporter.printFatalError("public_api command does not take any arguments.");
+ if (Args.size() > 1) {
+ Reporter.printFatalError(
+ "public_api command does not take more than one arguments.");
+ }
+
+ AttributeStyle PreferedStyle = AttributeStyle::Gnu;
+
+ for (auto &arg : Args) {
+ if (arg == "prefer-c23-attributes") {
+ PreferedStyle = AttributeStyle::C23;
+ }
+ if (arg == "prefer-no-attributes") {
+ PreferedStyle = AttributeStyle::None;
+ }
}
APIIndexer G(StdHeader, Records);
- writeAPIFromIndex(G, EntrypointNameList, OS);
+ writeAPIFromIndex(G, EntrypointNameList, OS, PreferedStyle);
}
} // namespace llvm_libc
diff --git a/libc/utils/HdrGen/PublicAPICommand.h b/libc/utils/HdrGen/PublicAPICommand.h
index fb0a7a81cf277a..035e1c71f4f12f 100644
--- a/libc/utils/HdrGen/PublicAPICommand.h
+++ b/libc/utils/HdrGen/PublicAPICommand.h
@@ -25,6 +25,8 @@ class RecordKeeper;
namespace llvm_libc {
+enum class AttributeStyle { None, Gnu, C23, Declspec };
+
class PublicAPICommand : public Command {
private:
const std::vector<std::string> &EntrypointNameList;
>From 029f563a799bb82b142b325c45a3a49bd539dd5d Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Mon, 29 Jan 2024 15:05:04 -0500
Subject: [PATCH 2/2] [libc][RFC] add support for function level attributes
---
libc/spec/spec.td | 7 +-
libc/spec/stdc.td | 7 +-
libc/utils/HdrGen/PublicAPICommand.cpp | 152 +++++++++++++------------
libc/utils/HdrGen/PublicAPICommand.h | 2 +-
4 files changed, 92 insertions(+), 76 deletions(-)
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index f0493da57df7ed..9ed4fa4a31de67 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -174,17 +174,18 @@ class GnuFunctionAttr<string attr> : FunctionAttr {
string Attr = attr;
string Style = "gnu";
}
-class C23FunctionAttr<string attr, string namespace> : FunctionAttr {
+class Cxx11FunctionAttr<string attr, string namespace> : FunctionAttr {
string Attr = attr;
string Namespace = namespace;
- string Style = "c23";
+ string Style = "cxx11";
}
class DeclspecFunctionAttr<string attr> : FunctionAttr {
string Attr = attr;
string Style = "declspec";
}
-class FunctionAttrSpec<list<FunctionAttr> instances> {
+class FunctionAttrSpec<string macro, list<FunctionAttr> instances> {
list<FunctionAttr> Instances = instances;
+ string Macro = macro;
}
class FunctionSpec<string name, RetValSpec return, list<ArgSpec> args, list<FunctionAttrSpec> attrs = []> {
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 43b81c4abaa0e6..a32a14812bec6f 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -26,6 +26,11 @@ def StdC : StandardSpec<"stdc"> {
[]
>;
+ FunctionAttrSpec ConstAttr = FunctionAttrSpec<"__LIBC_CONST_ATTR", [
+ Cxx11FunctionAttr<"const", "gnu">,
+ GnuFunctionAttr<"const">,
+ ]>;
+
HeaderSpec CType = HeaderSpec<
"ctype.h",
[], // Macros
@@ -364,7 +369,7 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"ceilf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"ceill", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
- FunctionSpec<"fabs", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"fabs", RetValSpec<DoubleType>, [ArgSpec<DoubleType>], [ConstAttr]>,
FunctionSpec<"fabsf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"fabsl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
FunctionSpec<"fabsf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>]>,
diff --git a/libc/utils/HdrGen/PublicAPICommand.cpp b/libc/utils/HdrGen/PublicAPICommand.cpp
index 26eb14c7589208..d24637db0f7888 100644
--- a/libc/utils/HdrGen/PublicAPICommand.cpp
+++ b/libc/utils/HdrGen/PublicAPICommand.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Record.h"
+#include <algorithm>
#include <llvm/ADT/STLExtras.h>
// Text blocks for macro definitions and type decls can be indented to
@@ -50,7 +51,7 @@ namespace llvm_libc {
void writeAPIFromIndex(APIIndexer &G,
std::vector<std::string> EntrypointNameList,
- llvm::raw_ostream &OS, AttributeStyle PreferedStyle) {
+ llvm::raw_ostream &OS) {
for (auto &Pair : G.MacroDefsMap) {
const std::string &Name = Pair.first;
if (G.MacroSpecMap.find(Name) == G.MacroSpecMap.end())
@@ -88,6 +89,71 @@ void writeAPIFromIndex(APIIndexer &G,
if (G.Enumerations.size() != 0)
OS << "};\n\n";
+ // declare macros for attributes
+ llvm::DenseMap<llvm::StringRef, llvm::Record *> MacroAttr;
+ for (auto &Name : EntrypointNameList) {
+ if (G.FunctionSpecMap.find(Name) == G.FunctionSpecMap.end()) {
+ continue;
+ }
+ llvm::Record *FunctionSpec = G.FunctionSpecMap[Name];
+ auto Attributes = FunctionSpec->getValueAsListOfDefs("Attributes");
+ for (auto *Attr : Attributes) {
+ MacroAttr[Attr->getValueAsString("Macro")] = Attr;
+ }
+ }
+
+ auto GetStyle = [](llvm::Record *Instance) {
+ auto Style = Instance->getValueAsString("Style");
+ if (Style == "cxx11")
+ return AttributeStyle::Cxx11;
+ if (Style == "gnu")
+ return AttributeStyle::Gnu;
+ return AttributeStyle::Declspec;
+ };
+
+ for (auto &[Macro, Attr] : MacroAttr) {
+ auto Instances = Attr->getValueAsListOfDefs("Instances");
+ llvm::SmallVector<std::pair<AttributeStyle, llvm::Record *>> Styles;
+ std::transform(Instances.begin(), Instances.end(),
+ std::back_inserter(Styles),
+ [&](llvm::Record *Instance)
+ -> std::pair<AttributeStyle, llvm::Record *> {
+ auto Style = GetStyle(Instance);
+ return {Style, Instance};
+ });
+ // Effectively sort on the first field
+ std::sort(Styles.begin(), Styles.end());
+ for (auto &[Style, Instance] : Styles) {
+ if (Style == AttributeStyle::Cxx11) {
+ OS << "#if !defined(" << Macro << ") && defined(__cplusplus)\n";
+ OS << "#define " << Macro << " [[";
+ auto Namespace = Instance->getValueAsString("Namespace");
+ if (Namespace != "")
+ OS << Namespace << "::";
+ OS << Instance->getValueAsString("Attr") << "]]\n";
+ OS << "#endif\n";
+ }
+ if (Style == AttributeStyle::Gnu) {
+ OS << "#if !defined(" << Macro << ") && defined(__GNUC__)\n";
+ OS << "#define " << Macro << " __attribute__((";
+ OS << Instance->getValueAsString("Attr") << "))\n";
+ OS << "#endif\n";
+ }
+ if (Style == AttributeStyle::Declspec) {
+ OS << "#if !defined(" << Macro << ") && defined(_MSC_VER)\n";
+ OS << "#define " << Macro << " __declspec(";
+ OS << Instance->getValueAsString("Attr") << ")\n";
+ OS << "#endif\n";
+ }
+ }
+ OS << "#if !defined(" << Macro << ")\n";
+ OS << "#define " << Macro << '\n';
+ OS << "#endif\n";
+ }
+
+ if (!MacroAttr.empty())
+ OS << '\n';
+
OS << "__BEGIN_C_DECLS\n\n";
for (auto &Name : EntrypointNameList) {
if (G.FunctionSpecMap.find(Name) == G.FunctionSpecMap.end()) {
@@ -103,61 +169,13 @@ void writeAPIFromIndex(APIIndexer &G,
llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
- auto GetStyle = [](llvm::Record *Instance) {
- auto Style = Instance->getValueAsString("Style");
- if (Style == "gnu")
- return AttributeStyle::Gnu;
- if (Style == "c23")
- return AttributeStyle::C23;
- if (Style == "declspec")
- return AttributeStyle::Declspec;
- return AttributeStyle::None;
- };
-
- if (PreferedStyle != AttributeStyle::None) {
- auto Attributes = FunctionSpec->getValueAsListOfDefs("Attributes");
- llvm::SmallVector<llvm::Record *> Attrs;
- for (auto *Attr : Attributes) {
- auto Instances = Attr->getValueAsListOfDefs("Instances");
- for (auto *Instance : Instances) {
- if (GetStyle(Instance) == PreferedStyle) {
- Attrs.push_back(Instance);
- }
- }
- }
-
- if (Attrs.size() != 0) {
- if (PreferedStyle == AttributeStyle::Gnu) {
- OS << "__attribute__((";
- llvm::interleaveComma(Attrs, OS, [&](llvm::Record *Instance) {
- OS << Instance->getValueAsString("Attr");
- });
- OS << ")) ";
- }
-
- if (PreferedStyle == AttributeStyle::C23) {
- OS << "__attribute__((";
- llvm::interleaveComma(Attrs, OS, [&](llvm::Record *Instance) {
- auto Namespace = Instance->getValueAsString("Namespace");
- if (Namespace != "")
- OS << Namespace << "::";
- OS << Instance->getValueAsString("Attr");
- });
- OS << ")) ";
- }
-
- if (PreferedStyle == AttributeStyle::Declspec) {
- OS << "__declspec(";
- llvm::interleave(
- Attrs.begin(), Attrs.end(),
- [&](llvm::Record *Instance) {
- OS << Instance->getValueAsString("Attr");
- },
- [&]() { OS << ' '; });
- OS << ") ";
- }
- }
- }
+ auto Attributes = FunctionSpec->getValueAsListOfDefs("Attributes");
+ llvm::interleave(
+ Attributes.begin(), Attributes.end(),
+ [&](llvm::Record *Attr) { OS << Attr->getValueAsString("Macro"); },
+ [&]() { OS << ' '; });
+ if (!Attributes.empty())
+ OS << ' ';
OS << G.getTypeAsString(ReturnType) << " " << Name << "(";
@@ -181,6 +199,10 @@ void writeAPIFromIndex(APIIndexer &G,
OS << "extern " << Type << " " << Name << ";\n";
}
OS << "__END_C_DECLS\n";
+
+ // undef the macros
+ for (auto &[Macro, Attr] : MacroAttr)
+ OS << "\n#undef " << Macro << '\n';
}
void writePublicAPI(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {}
@@ -191,24 +213,12 @@ void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader,
llvm::RecordKeeper &Records,
const Command::ErrorReporter &Reporter) const {
- if (Args.size() > 1) {
- Reporter.printFatalError(
- "public_api command does not take more than one arguments.");
- }
-
- AttributeStyle PreferedStyle = AttributeStyle::Gnu;
-
- for (auto &arg : Args) {
- if (arg == "prefer-c23-attributes") {
- PreferedStyle = AttributeStyle::C23;
- }
- if (arg == "prefer-no-attributes") {
- PreferedStyle = AttributeStyle::None;
- }
+ if (Args.size() != 0) {
+ Reporter.printFatalError("public_api command does not take any arguments.");
}
APIIndexer G(StdHeader, Records);
- writeAPIFromIndex(G, EntrypointNameList, OS, PreferedStyle);
+ writeAPIFromIndex(G, EntrypointNameList, OS);
}
} // namespace llvm_libc
diff --git a/libc/utils/HdrGen/PublicAPICommand.h b/libc/utils/HdrGen/PublicAPICommand.h
index 035e1c71f4f12f..72401cfe068e33 100644
--- a/libc/utils/HdrGen/PublicAPICommand.h
+++ b/libc/utils/HdrGen/PublicAPICommand.h
@@ -25,7 +25,7 @@ class RecordKeeper;
namespace llvm_libc {
-enum class AttributeStyle { None, Gnu, C23, Declspec };
+enum class AttributeStyle { Cxx11 = 0, Gnu = 1, Declspec = 2 };
class PublicAPICommand : public Command {
private:
More information about the libc-commits
mailing list