[libc-commits] [libc] [libc] newheadergen: script adjusted for cmake (PR #98825)

via libc-commits libc-commits at lists.llvm.org
Tue Jul 16 10:52:58 PDT 2024


https://github.com/aaryanshukla updated https://github.com/llvm/llvm-project/pull/98825

>From 93a1cc9fc7359e1dcdef70b494ca9bd8f96dbe95 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Sun, 14 Jul 2024 17:38:59 +0000
Subject: [PATCH 1/3] [libc] newheadergen: script adjusted for cmake

- added entrypoints and headerfile parameters depending on target
- fixed nits in yaml files causing errors
- tested with new cmake config
- cmake patch will be seperate
---
 libc/newhdrgen/header2.py           | 96 +++++++++++++++++++++++++++++
 libc/newhdrgen/yaml/features.yaml   |  8 +++
 libc/newhdrgen/yaml/pthread.yaml    | 31 +---------
 libc/newhdrgen/yaml/sys_random.yaml |  2 +-
 libc/newhdrgen/yaml/time.yaml       |  2 +-
 libc/newhdrgen/yaml_to_classes.py   | 91 +++++++++++++++++++--------
 6 files changed, 173 insertions(+), 57 deletions(-)
 create mode 100644 libc/newhdrgen/header2.py
 create mode 100644 libc/newhdrgen/yaml/features.yaml

diff --git a/libc/newhdrgen/header2.py b/libc/newhdrgen/header2.py
new file mode 100644
index 0000000000000..e115a7e8ef358
--- /dev/null
+++ b/libc/newhdrgen/header2.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+#
+# ===- HeaderFile Class for libc function headers  -----------*- python -*--==#
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ==-------------------------------------------------------------------------==#
+
+
+class HeaderFile:
+    def __init__(self, name):
+        self.name = name
+        self.macros = []
+        self.types = []
+        self.enumerations = []
+        self.objects = []
+        self.functions = []
+        self.includes = []
+
+    def add_macro(self, macro):
+        self.macros.append(macro)
+
+    def add_type(self, type_):
+        self.types.append(type_)
+
+    def add_enumeration(self, enumeration):
+        self.enumerations.append(enumeration)
+
+    def add_object(self, object):
+        self.objects.append(object)
+
+    def add_function(self, function):
+        self.functions.append(function)
+
+    def add_include(self, include):
+        self.includes.append(include)
+
+    def __str__(self):
+        content = []
+
+        content.append(
+            f"//===-- C standard declarations for {self.name} ------------------------------===//"
+        )
+        content.append("//")
+        content.append(
+            "// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions."
+        )
+        content.append("// See https://llvm.org/LICENSE.txt for license information.")
+        content.append("// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception")
+        content.append("//")
+        content.append(
+            "//===----------------------------------------------------------------------===//\n"
+        )
+
+        header_guard = f"__LLVM_LIBC_DECLARATIONS_{self.name.upper()[:-2]}_H"
+        content.append(f"#ifndef {header_guard}")
+        content.append(f"#define {header_guard}\n")
+
+        content.append("#ifndef __LIBC_ATTRS")
+        content.append("#define __LIBC_ATTRS")
+        content.append("#endif\n")
+
+        content.append("#ifdef __cplusplus")
+        content.append('extern "C" {')
+        content.append("#endif\n")
+
+        for include in self.includes:
+            content.append(str(include))
+
+        for macro in self.macros:
+            content.append(f"{macro}\n")
+
+        for type_ in self.types:
+            content.append(f"{type_}")
+
+        if self.enumerations:
+            combined_enum_content = ",\n  ".join(
+                str(enum) for enum in self.enumerations
+            )
+            content.append(f"\nenum {{\n  {combined_enum_content},\n}};")
+
+        for function in self.functions:
+            content.append(f"{function} __LIBC_ATTRS;\n")
+
+        for object in self.objects:
+            content.append(f"{object} __LIBC_ATTRS;\n")
+
+        content.append("#ifdef __cplusplus")
+        content.append("}")
+        content.append("#endif\n")
+
+        content.append(f"#endif")
+
+        return "\n".join(content)
diff --git a/libc/newhdrgen/yaml/features.yaml b/libc/newhdrgen/yaml/features.yaml
new file mode 100644
index 0000000000000..86bc0acfe89ed
--- /dev/null
+++ b/libc/newhdrgen/yaml/features.yaml
@@ -0,0 +1,8 @@
+header: features.h
+standards: 
+  - stdc
+macros: []
+types: []
+enums: []
+objects: []
+functions: []
diff --git a/libc/newhdrgen/yaml/pthread.yaml b/libc/newhdrgen/yaml/pthread.yaml
index 14a562082d5de..f22767eb1b752 100644
--- a/libc/newhdrgen/yaml/pthread.yaml
+++ b/libc/newhdrgen/yaml/pthread.yaml
@@ -13,33 +13,8 @@ types:
   - type_name: __pthread_start_t
   - type_name: __pthread_once_func_t
   - type_name: __atfork_callback_t
-enums:
-  - name: PTHREAD_CREATE_JOINABLE
-    value: 0x0
-  - name: PTHREAD_CREATE_DETACHED
-    value: 0x1
-  - name: PTHREAD_MUTEX_NORMAL
-    value: 0x0
-  - name: PTHREAD_MUTEX_ERRORCHECK
-    value: 0x1
-  - name: PTHREAD_MUTEX_RECURSIVE
-    value: 0x2
-  - name: PTHREAD_MUTEX_DEFAULT
-    value: 0x0
-  - name: PTHREAD_PROCESS_PRIVATE
-    value: 0x0
-  - name: PTHREAD_PROCESS_SHARED
-    value: 0x1
-  - name: PTHREAD_MUTEX_STALLED
-    value: 0x0
-  - name: PTHREAD_MUTEX_ROBUST
-    value: 0x1
-  - name: PTHREAD_RWLOCK_PREFER_READER_NP
-    value: 0
-  - name: PTHREAD_RWLOCK_PREFER_WRITER_NP
-    value: 1
-  - name: PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
-    value: 2
+  - type_name: pthread_rwlock_t
+enums: []
 functions:
   - name: pthread_atfork
     standards: 
@@ -184,7 +159,7 @@ functions:
   - name: pthread_exit
     standards: 
       - POSIX
-    return_type: __Noreturn void
+    return_type: _Noreturn void
     arguments:
       - type: void *
   - name: pthread_getname_np
diff --git a/libc/newhdrgen/yaml/sys_random.yaml b/libc/newhdrgen/yaml/sys_random.yaml
index 233fb2c7988cb..6d84056d7dd71 100644
--- a/libc/newhdrgen/yaml/sys_random.yaml
+++ b/libc/newhdrgen/yaml/sys_random.yaml
@@ -4,7 +4,7 @@ types:
   - type_name: ssize_t
   - type_name: size_t
 enums: []
-objects:
+objects: []
 functions:
   - name: getrandom
     standards: 
diff --git a/libc/newhdrgen/yaml/time.yaml b/libc/newhdrgen/yaml/time.yaml
index e7f8de65eeb75..220d4328dbbdb 100644
--- a/libc/newhdrgen/yaml/time.yaml
+++ b/libc/newhdrgen/yaml/time.yaml
@@ -15,7 +15,7 @@ functions:
       - stdc
     return_type: char *
     arguments:
-      - type: struct tm *
+      - type: const struct tm *
   - name: asctime_r
     standard: 
       - stdc
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index 6bccda8e03640..d88ba95ee3d6b 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -8,12 +8,11 @@
 #
 # ==-------------------------------------------------------------------------==#
 
-
 import yaml
 import argparse
-
 from pathlib import Path
 from header import HeaderFile
+from header2 import HeaderFile as HeaderFile2
 from class_implementation.classes.macro import Macro
 from class_implementation.classes.type import Type
 from class_implementation.classes.function import Function
@@ -22,18 +21,20 @@
 from class_implementation.classes.object import Object
 
 
-def yaml_to_classes(yaml_data):
+def yaml_to_classes(yaml_data, header_class, entry_points=None):
     """
     Convert YAML data to header classes.
 
     Args:
         yaml_data: The YAML data containing header specifications.
+        header_class: The class to use for creating the header (HeaderFile or HeaderFile2).
+        entry_points: A list of specific function names to include in the header.
 
     Returns:
         HeaderFile: An instance of HeaderFile populated with the data.
     """
     header_name = yaml_data.get("header")
-    header = HeaderFile(header_name)
+    header = header_class(header_name)
 
     for macro_data in yaml_data.get("macros", []):
         header.add_macro(Macro(macro_data["macro_name"], macro_data["macro_value"]))
@@ -49,12 +50,15 @@ def yaml_to_classes(yaml_data):
         )
 
     functions = yaml_data.get("functions", [])
+    if entry_points:
+        entry_points_set = set(entry_points)
+        functions = [f for f in functions if f["name"] in entry_points_set]
     sorted_functions = sorted(functions, key=lambda x: x["name"])
     guards = []
     guarded_function_dict = {}
     for function_data in sorted_functions:
         guard = function_data.get("guard", None)
-        if guard == None:
+        if guard is None:
             arguments = [arg["type"] for arg in function_data["arguments"]]
             attributes = function_data.get("attributes", None)
             standards = function_data.get("standards", None)
@@ -105,19 +109,21 @@ def yaml_to_classes(yaml_data):
     return header
 
 
-def load_yaml_file(yaml_file):
+def load_yaml_file(yaml_file, header_class, entry_points):
     """
     Load YAML file and convert it to header classes.
 
     Args:
-        yaml_file: The path to the YAML file.
+        yaml_file: Path to the YAML file.
+        header_class: The class to use for creating the header (HeaderFile or HeaderFile2).
+        entry_points: A list of specific function names to include in the header.
 
     Returns:
-        HeaderFile: An instance of HeaderFile populated with the data from the YAML file.
+        HeaderFile: An instance of HeaderFile populated with the data.
     """
     with open(yaml_file, "r") as f:
         yaml_data = yaml.safe_load(f)
-    return yaml_to_classes(yaml_data)
+    return yaml_to_classes(yaml_data, header_class, entry_points)
 
 
 def fill_public_api(header_str, h_def_content):
@@ -207,7 +213,14 @@ def increase_indent(self, flow=False, indentless=False):
     print(f"Added function {new_function.name} to {yaml_file}")
 
 
-def main(yaml_file, h_def_file, output_dir, add_function=None):
+def main(
+    yaml_file,
+    output_dir=None,
+    h_def_file=None,
+    add_function=None,
+    entry_points=None,
+    export_decls=False,
+):
     """
     Main function to generate header files from YAML and .h.def templates.
 
@@ -216,41 +229,50 @@ def main(yaml_file, h_def_file, output_dir, add_function=None):
         h_def_file: Path to the .h.def template file.
         output_dir: Directory to output the generated header file.
         add_function: Details of the function to be added to the YAML file (if any).
+        entry_points: A list of specific function names to include in the header.
+        export_decls: Flag to use HeaderFile2 for exporting declarations.
     """
-
     if add_function:
         add_function_to_yaml(yaml_file, add_function)
 
-    header = load_yaml_file(yaml_file)
-
-    with open(h_def_file, "r") as f:
-        h_def_content = f.read()
+    header_class = HeaderFile2 if export_decls else HeaderFile
+    header = load_yaml_file(yaml_file, header_class, entry_points)
 
     header_str = str(header)
-    final_header_content = fill_public_api(header_str, h_def_content)
 
-    output_file_name = Path(h_def_file).stem
-    output_file_path = Path(output_dir) / output_file_name
-
-    with open(output_file_path, "w") as f:
-        f.write(final_header_content)
+    if output_dir:
+        output_file_path = Path(output_dir)
+        if output_file_path.is_dir():
+            output_file_path /= f"{Path(yaml_file).stem}.h"
+    else:
+        output_file_path = Path(f"{Path(yaml_file).stem}.h")
+
+    if not export_decls and h_def_file:
+        with open(h_def_file, "r") as f:
+            h_def_content = f.read()
+        final_header_content = fill_public_api(header_str, h_def_content)
+        with open(output_file_path, "w") as f:
+            f.write(final_header_content)
+    else:
+        with open(output_file_path, "w") as f:
+            f.write(header_str)
 
     print(f"Generated header file: {output_file_path}")
 
 
 if __name__ == "__main__":
-    parser = argparse.ArgumentParser(
-        description="Generate header files from YAML and .h.def templates"
-    )
+    parser = argparse.ArgumentParser(description="Generate header files from YAML")
     parser.add_argument(
         "yaml_file", help="Path to the YAML file containing header specification"
     )
-    parser.add_argument("h_def_file", help="Path to the .h.def template file")
     parser.add_argument(
         "--output_dir",
-        default=".",
         help="Directory to output the generated header file",
     )
+    parser.add_argument(
+        "--h_def_file",
+        help="Path to the .h.def template file (required if not using --export_decls)",
+    )
     parser.add_argument(
         "--add_function",
         nargs=6,
@@ -264,6 +286,21 @@ def main(yaml_file, h_def_file, output_dir, add_function=None):
         ),
         help="Add a function to the YAML file",
     )
+    parser.add_argument(
+        "--e", action="append", help="Entry point to include", dest="entry_points"
+    )
+    parser.add_argument(
+        "--export-decls",
+        action="store_true",
+        help="Flag to use HeaderFile2 for exporting declarations",
+    )
     args = parser.parse_args()
 
-    main(args.yaml_file, args.h_def_file, args.output_dir, args.add_function)
+    main(
+        args.yaml_file,
+        args.output_dir,
+        args.h_def_file,
+        args.add_function,
+        args.entry_points,
+        args.export_decls,
+    )

>From 2c7abf3b56766a6a573e2b21d6722f40393c034b Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Mon, 15 Jul 2024 23:42:16 +0000
Subject: [PATCH 2/3] switched names for gpu_header file

- fixed NOEXCEPT to only be there for non-gpu
---
 .../class_implementation/classes/function.py  |  6 ++++--
 libc/newhdrgen/{header2.py => gpu_headers.py} | 20 +------------------
 libc/newhdrgen/header.py                      |  2 +-
 libc/newhdrgen/yaml_to_classes.py             |  2 +-
 4 files changed, 7 insertions(+), 23 deletions(-)
 rename libc/newhdrgen/{header2.py => gpu_headers.py} (79%)

diff --git a/libc/newhdrgen/class_implementation/classes/function.py b/libc/newhdrgen/class_implementation/classes/function.py
index da26358e74506..dbfeb7364a734 100644
--- a/libc/newhdrgen/class_implementation/classes/function.py
+++ b/libc/newhdrgen/class_implementation/classes/function.py
@@ -26,9 +26,11 @@ def __str__(self):
         attributes_str = " ".join(self.attributes)
         arguments_str = ", ".join(self.arguments)
         if attributes_str == "":
-            result = f"{self.return_type} {self.name}({arguments_str}) __NOEXCEPT;"
+            result = f"{self.return_type} {self.name}({arguments_str});"
         else:
-            result = f"{attributes_str} {self.return_type} {self.name}({arguments_str}) __NOEXCEPT;"
+            result = (
+                f"{attributes_str} {self.return_type} {self.name}({arguments_str});"
+            )
         if self.guard:
             result = f"#ifdef {self.guard}\n{result}\n#endif // {self.guard}"
         return result
diff --git a/libc/newhdrgen/header2.py b/libc/newhdrgen/gpu_headers.py
similarity index 79%
rename from libc/newhdrgen/header2.py
rename to libc/newhdrgen/gpu_headers.py
index e115a7e8ef358..645a830d04818 100644
--- a/libc/newhdrgen/header2.py
+++ b/libc/newhdrgen/gpu_headers.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# ===- HeaderFile Class for libc function headers  -----------*- python -*--==#
+# ===- HeaderFile Class for GPU --export-decls version function headers  -----------*- python -*--==#
 #
 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 # See https://llvm.org/LICENSE.txt for license information.
@@ -34,9 +34,6 @@ def add_object(self, object):
     def add_function(self, function):
         self.functions.append(function)
 
-    def add_include(self, include):
-        self.includes.append(include)
-
     def __str__(self):
         content = []
 
@@ -66,21 +63,6 @@ def __str__(self):
         content.append('extern "C" {')
         content.append("#endif\n")
 
-        for include in self.includes:
-            content.append(str(include))
-
-        for macro in self.macros:
-            content.append(f"{macro}\n")
-
-        for type_ in self.types:
-            content.append(f"{type_}")
-
-        if self.enumerations:
-            combined_enum_content = ",\n  ".join(
-                str(enum) for enum in self.enumerations
-            )
-            content.append(f"\nenum {{\n  {combined_enum_content},\n}};")
-
         for function in self.functions:
             content.append(f"{function} __LIBC_ATTRS;\n")
 
diff --git a/libc/newhdrgen/header.py b/libc/newhdrgen/header.py
index ca960b639ab10..1c227715991c9 100644
--- a/libc/newhdrgen/header.py
+++ b/libc/newhdrgen/header.py
@@ -58,7 +58,7 @@ def __str__(self):
         content.append("\n__BEGIN_C_DECLS\n")
 
         for function in self.functions:
-            content.append(str(function))
+            content.append(str(function) + "__NOEXCEPT")
             content.append("")
         for object in self.objects:
             content.append(str(object))
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index d88ba95ee3d6b..e49b4f5b2e62a 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -12,7 +12,7 @@
 import argparse
 from pathlib import Path
 from header import HeaderFile
-from header2 import HeaderFile as HeaderFile2
+from gpu_headers import HeaderFile as HeaderFile2
 from class_implementation.classes.macro import Macro
 from class_implementation.classes.type import Type
 from class_implementation.classes.function import Function

>From dfd6dbd23920d59a345c1be8c88563ffd5ce525f Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Tue, 16 Jul 2024 17:52:27 +0000
Subject: [PATCH 3/3] fixed nits with spacing and naming classes

---
 libc/newhdrgen/gpu_headers.py     |  4 ++--
 libc/newhdrgen/yaml_to_classes.py | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/libc/newhdrgen/gpu_headers.py b/libc/newhdrgen/gpu_headers.py
index 645a830d04818..cc13096cd47c1 100644
--- a/libc/newhdrgen/gpu_headers.py
+++ b/libc/newhdrgen/gpu_headers.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# ===- HeaderFile Class for GPU --export-decls version function headers  -----------*- python -*--==#
+# ===- GPU HeaderFile Class for --export-decls version --------*- python -*--==#
 #
 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 # See https://llvm.org/LICENSE.txt for license information.
@@ -9,7 +9,7 @@
 # ==-------------------------------------------------------------------------==#
 
 
-class HeaderFile:
+class GpuHeaderFile:
     def __init__(self, name):
         self.name = name
         self.macros = []
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index e49b4f5b2e62a..205bb35fe691a 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -12,7 +12,7 @@
 import argparse
 from pathlib import Path
 from header import HeaderFile
-from gpu_headers import HeaderFile as HeaderFile2
+from gpu_headers import GpuHeaderFile as GpuHeader
 from class_implementation.classes.macro import Macro
 from class_implementation.classes.type import Type
 from class_implementation.classes.function import Function
@@ -27,7 +27,7 @@ def yaml_to_classes(yaml_data, header_class, entry_points=None):
 
     Args:
         yaml_data: The YAML data containing header specifications.
-        header_class: The class to use for creating the header (HeaderFile or HeaderFile2).
+        header_class: The class to use for creating the header.
         entry_points: A list of specific function names to include in the header.
 
     Returns:
@@ -115,7 +115,7 @@ def load_yaml_file(yaml_file, header_class, entry_points):
 
     Args:
         yaml_file: Path to the YAML file.
-        header_class: The class to use for creating the header (HeaderFile or HeaderFile2).
+        header_class: The class to use for creating the header (HeaderFile or GpuHeader).
         entry_points: A list of specific function names to include in the header.
 
     Returns:
@@ -230,12 +230,12 @@ def main(
         output_dir: Directory to output the generated header file.
         add_function: Details of the function to be added to the YAML file (if any).
         entry_points: A list of specific function names to include in the header.
-        export_decls: Flag to use HeaderFile2 for exporting declarations.
+        export_decls: Flag to use GpuHeader for exporting declarations.
     """
     if add_function:
         add_function_to_yaml(yaml_file, add_function)
 
-    header_class = HeaderFile2 if export_decls else HeaderFile
+    header_class = GpuHeader if export_decls else HeaderFile
     header = load_yaml_file(yaml_file, header_class, entry_points)
 
     header_str = str(header)
@@ -292,7 +292,7 @@ def main(
     parser.add_argument(
         "--export-decls",
         action="store_true",
-        help="Flag to use HeaderFile2 for exporting declarations",
+        help="Flag to use GpuHeader for exporting declarations",
     )
     args = parser.parse_args()
 



More information about the libc-commits mailing list