[libc-commits] [libc] Add a script for helping with #147386 (PR #177583)
Nico Weber via libc-commits
libc-commits at lists.llvm.org
Fri Jan 23 05:44:49 PST 2026
https://github.com/nico updated https://github.com/llvm/llvm-project/pull/177583
>From 6ba433abc19468491658e8e2ae006c3e2b668ea8 Mon Sep 17 00:00:00 2001
From: Nico Weber <thakis at chromium.org>
Date: Fri, 23 Jan 2026 07:53:32 -0500
Subject: [PATCH 1/2] Add a script for helping with #147386
This script automated the mechanical parts of the move
(updating CMake and Bazel files; adding shim files) and writes
details on what manual steps to take.
I used the script to create the basis of
https://github.com/llvm/llvm-project/pull/177224
Script written with LLM assistance.
---
libc/tools/move_math_to_header.py | 563 ++++++++++++++++++++++++++++++
1 file changed, 563 insertions(+)
create mode 100755 libc/tools/move_math_to_header.py
diff --git a/libc/tools/move_math_to_header.py b/libc/tools/move_math_to_header.py
new file mode 100755
index 0000000000000..b4062d8bd75e6
--- /dev/null
+++ b/libc/tools/move_math_to_header.py
@@ -0,0 +1,563 @@
+#!/usr/bin/env python3
+"""
+Migration script to move LLVM libc math functions from
+libc/src/math/generic/<func>.cpp to header-only implementations in
+libc/src/__support/math/<func>.h.
+
+Usage:
+ libc/tools/move_math_to_header.py <func_name>
+"""
+
+import argparse
+import os
+import re
+import sys
+from pathlib import Path
+
+
+def find_llvm_root(start_path: Path) -> Path:
+ """Find the LLVM project root by looking for .git directory."""
+ current = start_path.resolve()
+ while current != current.parent:
+ if (current / ".git").exists() and (current / "libc").exists():
+ return current
+ current = current.parent
+ raise FileNotFoundError(
+ "Could not find LLVM project root. "
+ "Please specify --root or run from within the llvm-project directory."
+ )
+
+
+def read_file(path: Path) -> str:
+ """Read file content."""
+ with open(path, "r") as f:
+ return f.read()
+
+
+def write_file(path: Path, content: str) -> None:
+ """Write content to file."""
+ path.parent.mkdir(parents=True, exist_ok=True)
+ with open(path, "w") as f:
+ f.write(content)
+
+
+def extract_llvm_libc_function(content: str) -> tuple:
+ """
+ Extract function signature from LLVM_LIBC_FUNCTION macro.
+ Returns (return_type, func_name, params_with_types, param_names).
+ """
+ # Match LLVM_LIBC_FUNCTION(return_type, func_name, (params))
+ pattern = r"LLVM_LIBC_FUNCTION\s*\(\s*(\w+)\s*,\s*(\w+)\s*,\s*\(([^)]*)\)\s*\)"
+ match = re.search(pattern, content)
+ if not match:
+ raise ValueError("Could not find LLVM_LIBC_FUNCTION macro")
+
+ return_type = match.group(1)
+ func_name = match.group(2)
+ params_with_types = match.group(3).strip()
+
+ # Extract just parameter names
+ param_names = []
+ for param in params_with_types.split(","):
+ param = param.strip()
+ if param:
+ # Get the last word (parameter name)
+ parts = param.split()
+ if parts:
+ param_names.append(parts[-1])
+
+ return return_type, func_name, params_with_types, ", ".join(param_names)
+
+
+def transform_cpp_to_header(content: str, func_name: str) -> str:
+ """Transform the .cpp file content to a header-only implementation."""
+ lines = content.splitlines()
+ license_header = '\n'.join(lines[:7])
+
+ includes_end = lines.index('namespace LIBC_NAMESPACE_DECL {')
+ include_lines = lines[7:includes_end]
+ header_includes = []
+ for inc in include_lines:
+ # Skip public header
+ if f'"src/math/{func_name}.h"' in inc:
+ continue
+ # Skip common.h (contains LLVM_LIBC_FUNCTION)
+ if '"src/__support/common.h"' in inc:
+ continue
+ # Rely on clang-format to figure out include order.
+ header_includes.append(inc.replace('src/__support/math/', ''))
+ headers = '\n'.join(header_includes)
+
+ func_upper = func_name.upper()
+
+ header = license_header + f"""
+
+#ifndef LIBC_SRC___SUPPORT_MATH_{func_upper}_H
+#define LIBC_SRC___SUPPORT_MATH_{func_upper}_H
+
+{headers}
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+// XXX put function implementation here
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+"""
+ header += f"#endif // LIBC_SRC___SUPPORT_MATH_{func_upper}_H\n"
+
+ return header
+
+
+def create_shared_header(func_name: str) -> str:
+ """Create the shared header file content."""
+ func_upper = func_name.upper()
+
+ prefix = f"//===-- Shared {func_name} function "
+ suffix = "-*- C++ -*-===//"
+ dashes_needed = 80 - len(prefix) - len(suffix)
+ dashes = "-" * dashes_needed
+
+ return f"""{prefix}{dashes}{suffix}
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SHARED_MATH_{func_upper}_H
+#define LLVM_LIBC_SHARED_MATH_{func_upper}_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/{func_name}.h"
+
+namespace LIBC_NAMESPACE_DECL {{
+namespace shared {{
+
+using math::{func_name};
+
+}} // namespace shared
+}} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_{func_upper}_H
+"""
+
+
+def create_wrapper_cpp(content: str, func_name: str, return_type: str, params_with_types: str, param_names: str) -> str:
+ """Create the simplified wrapper .cpp file."""
+ license_header = '\n'.join(content.splitlines()[:7])
+ return license_header + f"""
+
+#include "src/math/{func_name}.h"
+#include "src/__support/math/{func_name}.h"
+
+namespace LIBC_NAMESPACE_DECL {{
+
+LLVM_LIBC_FUNCTION({return_type}, {func_name}, ({params_with_types})) {{ return math::{func_name}({param_names}); }}
+
+}} // namespace LIBC_NAMESPACE_DECL
+
+// FIXME: Move this to the header:
+""" + content
+
+
+def extract_cmake_depends(cmake_content: str, func_name: str) -> list:
+ """Extract DEPENDS list from add_entrypoint_object for the given function."""
+ # Find the add_entrypoint_object block for this function
+ pattern = rf"add_entrypoint_object\s*\(\s*{re.escape(func_name)}\s+"
+ match = re.search(pattern, cmake_content)
+ if not match:
+ return []
+
+ # Find the DEPENDS section
+ start = match.end()
+ # Find the closing paren, accounting for nested parens
+ paren_count = 1
+ end = start
+ for i, char in enumerate(cmake_content[start:], start):
+ if char == "(":
+ paren_count += 1
+ elif char == ")":
+ paren_count -= 1
+ if paren_count == 0:
+ end = i
+ break
+
+ block = cmake_content[match.start() : end + 1]
+
+ # Extract DEPENDS entries
+ depends_match = re.search(r"DEPENDS\s+(.*?)(?:\)|$)", block, re.DOTALL)
+ if not depends_match:
+ return []
+
+ depends_text = depends_match.group(1)
+ # Split by whitespace and filter
+ deps = []
+ for line in depends_text.split("\n"):
+ line = line.strip()
+ # Skip comments and empty lines
+ if not line or line.startswith("#"):
+ continue
+ # Stop if we hit another keyword
+ if line in ["SRCS", "HDRS", "COMPILE_OPTIONS"]:
+ break
+ # Skip libc.src.__support.common as it's only for LLVM_LIBC_FUNCTION,
+ # which isn't needed in the new header.
+ if "libc.src.__support.common" in line:
+ continue
+ deps.append(line)
+
+ return deps
+
+
+def update_generic_cmake(cmake_path: Path, func_name: str) -> str:
+ """Update the generic CMakeLists.txt to simplify the entrypoint."""
+ content = read_file(cmake_path)
+
+ # Find the add_entrypoint_object block
+ pattern = rf"(add_entrypoint_object\s*\(\s*{re.escape(func_name)}\s+)"
+ match = re.search(pattern, content)
+ if not match:
+ raise ValueError(f"Could not find add_entrypoint_object for {func_name}")
+
+ # Find the full block
+ start = match.start()
+ paren_count = 0
+ end = start
+ found_open = False
+ for i, char in enumerate(content[start:], start):
+ if char == "(":
+ paren_count += 1
+ found_open = True
+ elif char == ")":
+ paren_count -= 1
+ if found_open and paren_count == 0:
+ end = i + 1
+ break
+
+ # Create new simplified block
+ new_block = f"""add_entrypoint_object(
+ {func_name}
+ SRCS
+ {func_name}.cpp
+ HDRS
+ ../{func_name}.h
+ DEPENDS
+ libc.src.__support.math.{func_name}
+)"""
+
+ return content[:start] + new_block + content[end:]
+
+
+def transform_deps_for_math_cmake(deps: list) -> list:
+ """Transform dependencies for the math CMakeLists.txt."""
+ result = []
+ for dep in deps:
+ dep = dep.strip()
+ if not dep:
+ continue
+ # Convert libc.src.__support.math.X to .X
+ if dep.startswith("libc.src.__support.math."):
+ short_name = dep.replace("libc.src.__support.math.", ".")
+ result.append(short_name)
+ else:
+ result.append(dep)
+ return sorted(result)
+
+
+def update_support_math_cmake(cmake_path: Path, func_name: str, deps: list) -> str:
+ """Add new add_header_library entry to support/math CMakeLists.txt."""
+ content = read_file(cmake_path)
+
+ transformed_deps = transform_deps_for_math_cmake(deps)
+
+ # Build the new entry
+ deps_str = "\n ".join(transformed_deps) if transformed_deps else ""
+ new_entry = f"""
+add_header_library(
+ {func_name}
+ HDRS
+ {func_name}.h
+ DEPENDS
+ {deps_str}
+)
+"""
+
+ return content.rstrip() + "\n" + new_entry
+
+
+def update_shared_math_h(path: Path, func_name: str) -> str:
+ """Add include for new shared header to shared/math.h."""
+ content = read_file(path)
+
+ new_include = f'#include "math/{func_name}.h"'
+
+ # Find the last #include "math/ line and insert after it
+ lines = content.split("\n")
+ insert_idx = 0
+ for i, line in enumerate(lines):
+ if line.startswith('#include "math/'):
+ insert_idx = i + 1
+
+ # Insert alphabetically
+ for i, line in enumerate(lines):
+ if line.startswith('#include "math/'):
+ # Extract the function name from the include
+ match = re.search(r'#include "math/(\w+)\.h"', line)
+ if match and match.group(1) > func_name:
+ insert_idx = i
+ break
+
+ lines.insert(insert_idx, new_include)
+ return "\n".join(lines)
+
+
+def update_shared_test_cmake(path: Path, func_name: str) -> str:
+ """Add dependency to shared test CMakeLists.txt."""
+ content = read_file(path)
+
+ new_dep = f" libc.src.__support.math.{func_name}"
+
+ # Find the DEPENDS section in add_fp_unittest
+ # Insert before the closing paren of the DEPENDS block
+ lines = content.split("\n")
+ result = []
+ in_depends = False
+
+ for i, line in enumerate(lines):
+ if "DEPENDS" in line:
+ in_depends = True
+ if in_depends and line.strip() == ")":
+ # Check if dependency already exists
+ if new_dep.strip() not in content:
+ result.append(new_dep)
+ in_depends = False
+ result.append(line)
+
+ return "\n".join(result)
+
+
+def extract_bazel_deps(bazel_content: str, func_name: str) -> list:
+ """Extract additional_deps from libc_math_function entry in BUILD.bazel."""
+ # Find the libc_math_function entry
+ pattern = rf'libc_math_function\s*\(\s*name\s*=\s*"{re.escape(func_name)}"'
+ match = re.search(pattern, bazel_content)
+ if not match:
+ return []
+
+ # Find the closing paren
+ start = match.start()
+ paren_count = 0
+ end = start
+ found_open = False
+ for i, char in enumerate(bazel_content[start:], start):
+ if char == "(":
+ paren_count += 1
+ found_open = True
+ elif char == ")":
+ paren_count -= 1
+ if found_open and paren_count == 0:
+ end = i + 1
+ break
+
+ block = bazel_content[start:end]
+
+ # Extract additional_deps
+ deps_match = re.search(r"additional_deps\s*=\s*\[(.*?)\]", block, re.DOTALL)
+ if not deps_match:
+ return []
+
+ deps_text = deps_match.group(1)
+ deps = []
+ for match in re.finditer(r'"([^"]+)"', deps_text):
+ deps.append(match.group(1))
+
+ return deps
+
+
+def update_bazel_build(bazel_path: Path, func_name: str) -> str:
+ """Update BUILD.bazel with new support library and updated math function."""
+ content = read_file(bazel_path)
+
+ # Extract deps from existing libc_math_function
+ deps = extract_bazel_deps(content, func_name)
+
+ # Create new libc_support_library entry
+ deps_str = '",\n "'.join(deps) if deps else ""
+ new_support_lib = f'''libc_support_library(
+ name = "__support_math_{func_name}",
+ hdrs = ["src/__support/math/{func_name}.h"],
+ deps = [
+ "{deps_str}",
+ ],
+)
+'''
+
+ # Find where to insert (after other __support_math_ entries, alphabetically)
+ # Look for existing __support_math_ entries
+ insert_pos = 0
+ for match in re.finditer(r'libc_support_library\s*\(\s*name\s*=\s*"__support_math_(\w+)"', content):
+ existing_name = match.group(1)
+ if existing_name < func_name:
+ # Find end of this block
+ block_start = match.start()
+ paren_count = 0
+ found_open = False
+ for i, char in enumerate(content[block_start:], block_start):
+ if char == "(":
+ paren_count += 1
+ found_open = True
+ elif char == ")":
+ paren_count -= 1
+ if found_open and paren_count == 0:
+ insert_pos = i + 1
+ break
+ elif existing_name > func_name:
+ # Insert before this entry
+ if insert_pos == 0:
+ insert_pos = match.start()
+ break
+
+ if insert_pos > 0:
+ # Find next newline after insert_pos
+ next_newline = content.find("\n", insert_pos)
+ if next_newline != -1:
+ insert_pos = next_newline + 1
+
+ # Insert the new support library
+ content = content[:insert_pos] + "\n" + new_support_lib + content[insert_pos:]
+
+ # Update the libc_math_function entry
+ pattern = rf'(libc_math_function\s*\(\s*name\s*=\s*"{re.escape(func_name)}"\s*,\s*additional_deps\s*=\s*\[)[^\]]*(\]\s*,?\s*\))'
+ replacement = rf'\1\n ":__support_math_{func_name}",\n \2'
+ content = re.sub(pattern, replacement, content, flags=re.DOTALL)
+
+ return content
+
+
+def migrate_function(func_name: str, root: Path, dry_run: bool = False) -> None:
+ """Perform the full migration of a math function."""
+
+
+ src_cpp = root / "libc" / "src" / "math" / "generic" / f"{func_name}.cpp"
+ if not src_cpp.exists():
+ raise FileNotFoundError(f"Source file not found: {src_cpp}")
+
+ support_header = root / "libc" / "src" / "__support" / "math" / f"{func_name}.h"
+ if support_header.exists() and not dry_run:
+ raise FileExistsError(f"Header already exists: {support_header}")
+
+ print(f"Migrating {func_name}...")
+
+ src_content = read_file(src_cpp)
+ return_type, _, params_with_types, param_names = extract_llvm_libc_function(src_content)
+ print(f" Function signature: {return_type} {func_name}({params_with_types})")
+
+ print("\nGenerating files...")
+
+ generic_cmake = root / "libc" / "src" / "math" / "generic" / "CMakeLists.txt"
+ cmake_content = read_file(generic_cmake)
+ deps = extract_cmake_depends(cmake_content, func_name)
+ updated_generic_cmake = update_generic_cmake(generic_cmake, func_name)
+ print(f" Updating: {generic_cmake}")
+ if not dry_run:
+ write_file(generic_cmake, updated_generic_cmake)
+
+ support_cmake = root / "libc" / "src" / "__support" / "math" / "CMakeLists.txt"
+ updated_support_cmake = update_support_math_cmake(support_cmake, func_name, deps)
+ print(f" Updating: {support_cmake}")
+ if not dry_run:
+ write_file(support_cmake, updated_support_cmake)
+
+ test_cmake = root / "libc" / "test" / "shared" / "CMakeLists.txt"
+ updated_test_cmake = update_shared_test_cmake(test_cmake, func_name)
+ print(f" Updating: {test_cmake}")
+ if not dry_run:
+ write_file(test_cmake, updated_test_cmake)
+
+ bazel_build = root / "utils" / "bazel" / "llvm-project-overlay" / "libc" / "BUILD.bazel"
+ updated_bazel = update_bazel_build(bazel_build, func_name)
+ print(f" Updating: {bazel_build}")
+ if not dry_run:
+ write_file(bazel_build, updated_bazel)
+
+ shared_header = root / "libc" / "shared" / "math" / f"{func_name}.h"
+ shared_content = create_shared_header(func_name)
+ print(f" Creating: {shared_header}")
+ if not dry_run:
+ write_file(shared_header, shared_content)
+
+ shared_math_h = root / "libc" / "shared" / "math.h"
+ updated_shared_math = update_shared_math_h(shared_math_h, func_name)
+ print(f" Updating: {shared_math_h}")
+ if not dry_run:
+ write_file(shared_math_h, updated_shared_math)
+
+ # FIXME: More automation for the files below?
+
+ header_content = transform_cpp_to_header(src_content, func_name)
+ print(f" Creating: {support_header}")
+ if not dry_run:
+ write_file(support_header, header_content)
+
+ wrapper_content = create_wrapper_cpp(src_content, func_name, return_type, params_with_types, param_names)
+ print(f" Updating: {src_cpp}")
+ if not dry_run:
+ write_file(src_cpp, wrapper_content)
+
+ test_cpp = root / "libc" / "test" / "shared" / "shared_math_test.cpp"
+
+ print("\nMigration complete!")
+ print("\nNext steps:")
+ print(f" 1. git add {shared_header} {support_header}")
+ print(f" 2. Move code from {src_cpp} to {support_header}")
+ print(f" * Replace `namespace {` with `namespace {func_name}_internal` (including closing comment)")
+ print(f" * Add `using namespace {func_name}_internal` to top of main function")
+ print(f" * Make all functions `LIBC_INLINE static`")
+ print(f" * Make all variables `LIBC_INLINE_VAR`")
+ print(f" 3. Add a test to {test_cpp}")
+ print(f""" 4. git commit -am '[libc][math] Refactor {func_name} implementation to header-only in src/__support/math folder.
+
+Part of #147386
+
+in preparation for:
+
+https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450'""")
+ print(f" 5. Run `git clang-format main` to fix include order")
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Migrate LLVM libc math function to header-only implementation"
+ )
+ parser.add_argument("func_name", help="Name of the math function to migrate")
+ parser.add_argument(
+ "--root",
+ type=Path,
+ help="Path to llvm-project root (auto-detected if not specified)",
+ )
+ parser.add_argument(
+ "--dry-run",
+ action="store_true",
+ help="Print what would be done without making changes",
+ )
+
+ args = parser.parse_args()
+
+ if args.root:
+ root = args.root.resolve()
+ else:
+ root = find_llvm_root(Path.cwd())
+
+ print(f"LLVM project root: {root}")
+
+ migrate_function(args.func_name, root, args.dry_run)
+
+
+if __name__ == "__main__":
+ main()
>From 721168fb2adb2b77151f0ae93ce6adf01e01788f Mon Sep 17 00:00:00 2001
From: Nico Weber <thakis at chromium.org>
Date: Fri, 23 Jan 2026 08:44:36 -0500
Subject: [PATCH 2/2] run `uvx black`
---
libc/tools/move_math_to_header.py | 70 +++++++++++++++++++++----------
1 file changed, 47 insertions(+), 23 deletions(-)
diff --git a/libc/tools/move_math_to_header.py b/libc/tools/move_math_to_header.py
index b4062d8bd75e6..1278eacb3b8a7 100755
--- a/libc/tools/move_math_to_header.py
+++ b/libc/tools/move_math_to_header.py
@@ -72,9 +72,9 @@ def extract_llvm_libc_function(content: str) -> tuple:
def transform_cpp_to_header(content: str, func_name: str) -> str:
"""Transform the .cpp file content to a header-only implementation."""
lines = content.splitlines()
- license_header = '\n'.join(lines[:7])
+ license_header = "\n".join(lines[:7])
- includes_end = lines.index('namespace LIBC_NAMESPACE_DECL {')
+ includes_end = lines.index("namespace LIBC_NAMESPACE_DECL {")
include_lines = lines[7:includes_end]
header_includes = []
for inc in include_lines:
@@ -85,29 +85,32 @@ def transform_cpp_to_header(content: str, func_name: str) -> str:
if '"src/__support/common.h"' in inc:
continue
# Rely on clang-format to figure out include order.
- header_includes.append(inc.replace('src/__support/math/', ''))
- headers = '\n'.join(header_includes)
+ header_includes.append(inc.replace("src/__support/math/", ""))
+ headers = "\n".join(header_includes)
func_upper = func_name.upper()
- header = license_header + f"""
+ header = (
+ license_header
+ + f"""
#ifndef LIBC_SRC___SUPPORT_MATH_{func_upper}_H
#define LIBC_SRC___SUPPORT_MATH_{func_upper}_H
{headers}
-namespace LIBC_NAMESPACE_DECL {
+namespace LIBC_NAMESPACE_DECL {{
-namespace math {
+namespace math {{
// XXX put function implementation here
-} // namespace math
+}} // namespace math
-} // namespace LIBC_NAMESPACE_DECL
+}} // namespace LIBC_NAMESPACE_DECL
"""
+ )
header += f"#endif // LIBC_SRC___SUPPORT_MATH_{func_upper}_H\n"
return header
@@ -148,10 +151,18 @@ def create_shared_header(func_name: str) -> str:
"""
-def create_wrapper_cpp(content: str, func_name: str, return_type: str, params_with_types: str, param_names: str) -> str:
+def create_wrapper_cpp(
+ content: str,
+ func_name: str,
+ return_type: str,
+ params_with_types: str,
+ param_names: str,
+) -> str:
"""Create the simplified wrapper .cpp file."""
- license_header = '\n'.join(content.splitlines()[:7])
- return license_header + f"""
+ license_header = "\n".join(content.splitlines()[:7])
+ return (
+ license_header
+ + f"""
#include "src/math/{func_name}.h"
#include "src/__support/math/{func_name}.h"
@@ -163,7 +174,9 @@ def create_wrapper_cpp(content: str, func_name: str, return_type: str, params_wi
}} // namespace LIBC_NAMESPACE_DECL
// FIXME: Move this to the header:
-""" + content
+"""
+ + content
+ )
def extract_cmake_depends(cmake_content: str, func_name: str) -> list:
@@ -389,19 +402,21 @@ def update_bazel_build(bazel_path: Path, func_name: str) -> str:
# Create new libc_support_library entry
deps_str = '",\n "'.join(deps) if deps else ""
- new_support_lib = f'''libc_support_library(
+ new_support_lib = f"""libc_support_library(
name = "__support_math_{func_name}",
hdrs = ["src/__support/math/{func_name}.h"],
deps = [
"{deps_str}",
],
)
-'''
+"""
# Find where to insert (after other __support_math_ entries, alphabetically)
# Look for existing __support_math_ entries
insert_pos = 0
- for match in re.finditer(r'libc_support_library\s*\(\s*name\s*=\s*"__support_math_(\w+)"', content):
+ for match in re.finditer(
+ r'libc_support_library\s*\(\s*name\s*=\s*"__support_math_(\w+)"', content
+ ):
existing_name = match.group(1)
if existing_name < func_name:
# Find end of this block
@@ -443,7 +458,6 @@ def update_bazel_build(bazel_path: Path, func_name: str) -> str:
def migrate_function(func_name: str, root: Path, dry_run: bool = False) -> None:
"""Perform the full migration of a math function."""
-
src_cpp = root / "libc" / "src" / "math" / "generic" / f"{func_name}.cpp"
if not src_cpp.exists():
raise FileNotFoundError(f"Source file not found: {src_cpp}")
@@ -455,7 +469,9 @@ def migrate_function(func_name: str, root: Path, dry_run: bool = False) -> None:
print(f"Migrating {func_name}...")
src_content = read_file(src_cpp)
- return_type, _, params_with_types, param_names = extract_llvm_libc_function(src_content)
+ return_type, _, params_with_types, param_names = extract_llvm_libc_function(
+ src_content
+ )
print(f" Function signature: {return_type} {func_name}({params_with_types})")
print("\nGenerating files...")
@@ -480,7 +496,9 @@ def migrate_function(func_name: str, root: Path, dry_run: bool = False) -> None:
if not dry_run:
write_file(test_cmake, updated_test_cmake)
- bazel_build = root / "utils" / "bazel" / "llvm-project-overlay" / "libc" / "BUILD.bazel"
+ bazel_build = (
+ root / "utils" / "bazel" / "llvm-project-overlay" / "libc" / "BUILD.bazel"
+ )
updated_bazel = update_bazel_build(bazel_build, func_name)
print(f" Updating: {bazel_build}")
if not dry_run:
@@ -505,7 +523,9 @@ def migrate_function(func_name: str, root: Path, dry_run: bool = False) -> None:
if not dry_run:
write_file(support_header, header_content)
- wrapper_content = create_wrapper_cpp(src_content, func_name, return_type, params_with_types, param_names)
+ wrapper_content = create_wrapper_cpp(
+ src_content, func_name, return_type, params_with_types, param_names
+ )
print(f" Updating: {src_cpp}")
if not dry_run:
write_file(src_cpp, wrapper_content)
@@ -516,18 +536,22 @@ def migrate_function(func_name: str, root: Path, dry_run: bool = False) -> None:
print("\nNext steps:")
print(f" 1. git add {shared_header} {support_header}")
print(f" 2. Move code from {src_cpp} to {support_header}")
- print(f" * Replace `namespace {` with `namespace {func_name}_internal` (including closing comment)")
+ print(
+ f" * Replace `namespace {{` with `namespace {func_name}_internal` (including closing comment)"
+ )
print(f" * Add `using namespace {func_name}_internal` to top of main function")
print(f" * Make all functions `LIBC_INLINE static`")
print(f" * Make all variables `LIBC_INLINE_VAR`")
print(f" 3. Add a test to {test_cpp}")
- print(f""" 4. git commit -am '[libc][math] Refactor {func_name} implementation to header-only in src/__support/math folder.
+ print(
+ f""" 4. git commit -am '[libc][math] Refactor {func_name} implementation to header-only in src/__support/math folder.
Part of #147386
in preparation for:
-https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450'""")
+https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450'"""
+ )
print(f" 5. Run `git clang-format main` to fix include order")
More information about the libc-commits
mailing list