[libc-commits] [libc] [libc][RFC] add support for function level attributes (PR #79891)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Tue Jan 30 08:48:53 PST 2024


================
@@ -87,6 +89,94 @@ 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;
+  };
+
+  auto GetNamespace = [](llvm::Record *Instance) {
+    auto Namespace = Instance->getValueAsString("Namespace");
+    // Empty namespace is likely to be most standard-compliant.
+    if (Namespace.empty())
+      return AttributeNamespace::None;
+    // Dispatch clang version before gnu version.
+    if (Namespace == "clang")
+      return AttributeNamespace::Clang;
+    return AttributeNamespace::Gnu;
+  };
+
+  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(), [&](auto &a, auto &b) {
+      if (a.first == AttributeStyle::Cxx11 && b.first == AttributeStyle::Cxx11)
+        return GetNamespace(a.second) < GetNamespace(b.second);
+      return a.first < b.first;
+    });
+    for (auto &[Style, Instance] : Styles) {
+      if (Style == AttributeStyle::Cxx11) {
+        OS << "#if !defined(" << Macro << ") && defined(__cplusplus)";
+        auto Namespace = GetNamespace(Instance);
+        if (Namespace == AttributeNamespace::Clang)
+          OS << " && defined(__clang__)\n";
+        else if (Namespace == AttributeNamespace::Gnu)
+          OS << " && defined(__GNUC__)\n";
+        else
+          OS << '\n';
+        OS << "#define " << Macro << " [[";
+        if (Namespace == AttributeNamespace::Clang)
+          OS << "clang::";
+        else if (Namespace == AttributeNamespace::Gnu)
+          OS << "gnu::";
+        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";
+      }
----------------
nickdesaulniers wrote:

Consider making these into helper functions. `writeAPIFromIndex` is already too long and needs to be broken up for readability.

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


More information about the libc-commits mailing list