Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc] newheadergen: script adjusted for cmake #98825

Merged
merged 8 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libc/newhdrgen/class_implementation/classes/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ 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})"
return result
78 changes: 78 additions & 0 deletions libc/newhdrgen/gpu_headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ==-------------------------------------------------------------------------==#


class GpuHeaderFile:
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 __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 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)
10 changes: 5 additions & 5 deletions libc/newhdrgen/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,29 @@ def __str__(self):
current_guard = None
for function in self.functions:
if function.guard == None:
content.append(str(function))
content.append(str(function) + "__NOEXCEPT")
content.append("")
else:
if current_guard == None:
current_guard = function.guard
content.append(f"#ifdef {current_guard}")
content.append(str(function))
content.append(str(function) + "__NOEXCEPT")
content.append("")
elif current_guard == function.guard:
content.append(str(function))
content.append(str(function) + "__NOEXCEPT")
content.append("")
else:
content.pop()
content.append(f"#endif // {current_guard}")
content.append("")
current_guard = function.guard
content.append(f"#ifdef {current_guard}")
content.append(str(function))
content.append(str(function) + "__NOEXCEPT")
content.append("")
if current_guard != None:
content.pop()
content.append(f"#endif // {current_guard}")
content.append("")
content.append("")

for object in self.objects:
content.append(str(object))
Expand Down
8 changes: 8 additions & 0 deletions libc/newhdrgen/yaml/features.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
header: features.h
standards:
- stdc
macros: []
types: []
enums: []
objects: []
functions: []
31 changes: 3 additions & 28 deletions libc/newhdrgen/yaml/pthread.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did these get removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was already in the h.def prior so we were duplicating enums.

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:
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libc/newhdrgen/yaml/sys/sys_random.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ types:
- type_name: ssize_t
- type_name: size_t
enums: []
objects:
objects: []
functions:
- name: getrandom
standards:
Expand Down
2 changes: 1 addition & 1 deletion libc/newhdrgen/yaml/time.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ functions:
- stdc
return_type: char *
arguments:
- type: struct tm *
- type: const struct tm *
- name: asctime_r
standard:
- stdc
Expand Down
91 changes: 64 additions & 27 deletions libc/newhdrgen/yaml_to_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
#
# ==-------------------------------------------------------------------------==#


import yaml
import argparse

from pathlib import Path
from header import HeaderFile
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
Expand All @@ -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.
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"]))
Expand All @@ -49,12 +50,15 @@ def yaml_to_classes(yaml_data):
)

functions = yaml_data.get("functions", [])
if entry_points:
entry_points_set = set(entry_points)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this set made?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line after when checking for the names, sets have a faster operation time for checking because we are just seeing if the func name is in the set rather than scanning through all of entry_points everytime

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)
Expand Down Expand Up @@ -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 GpuHeader).
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):
Expand Down Expand Up @@ -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.

Expand All @@ -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 GpuHeader 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 = GpuHeader 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,
Expand All @@ -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 GpuHeader 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,
)
Loading