[libc-commits] [libc] Libc/attribute (PR #79891)

via libc-commits libc-commits at lists.llvm.org
Mon Jan 29 12:06:37 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Schrodinger ZHU Yifan (SchrodingerZhu)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/79891.diff


4 Files Affected:

- (modified) libc/spec/spec.td (+21-1) 
- (modified) libc/spec/stdc.td (+6-1) 
- (modified) libc/utils/HdrGen/PublicAPICommand.cpp (+79) 
- (modified) libc/utils/HdrGen/PublicAPICommand.h (+2) 


``````````diff
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 818cfaee6b61c2b..9ed4fa4a31de678 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -169,10 +169,30 @@ 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 Cxx11FunctionAttr<string attr, string namespace> : FunctionAttr {
+  string Attr = attr;
+  string Namespace = namespace;
+  string Style = "cxx11";
+}
+class DeclspecFunctionAttr<string attr> : FunctionAttr {
+  string Attr = attr;
+  string Style = "declspec";
+}
+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 = []> {
   string Name = name;
   RetValSpec Return = return;
   list<ArgSpec> Args = args;
+  list<FunctionAttrSpec> Attributes = attrs;
 }
 
 class ObjectSpec<string name, string type> {
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 43b81c4abaa0e6b..a32a14812bec6fb 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 b1c7a072658ffbd..d24637db0f7888f 100644
--- a/libc/utils/HdrGen/PublicAPICommand.cpp
+++ b/libc/utils/HdrGen/PublicAPICommand.cpp
@@ -15,6 +15,8 @@
 #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
 // suit the surrounding tablegen listing. We need to dedent such blocks
@@ -87,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()) {
@@ -102,6 +169,14 @@ void writeAPIFromIndex(APIIndexer &G,
     llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
     llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
 
+    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 << "(";
 
     auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
@@ -124,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) {}
diff --git a/libc/utils/HdrGen/PublicAPICommand.h b/libc/utils/HdrGen/PublicAPICommand.h
index fb0a7a81cf277a3..72401cfe068e33a 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 { Cxx11 = 0, Gnu = 1, Declspec = 2 };
+
 class PublicAPICommand : public Command {
 private:
   const std::vector<std::string> &EntrypointNameList;

``````````

</details>


https://github.com/llvm/llvm-project/pull/79891


More information about the libc-commits mailing list