[libc] delete hdrgen (#117220)

Thanks to the effort of @RoseZhang03 and @aaryanshukla under the
guidance of
@michaelrj-google and @amykhuang, we now have newhdrgen and no longer
have a
dependency on TableGen and thus LLVM in order to start bootstrapping a
full
build.

This PR removes:
- LIBC_HDRGEN_EXE; the in tree newhdrgen is the only hdrgen that can be
used.
- LIBC_USE_NEW_HEADER_GEN; newhdrgen is the default and only option.
- LIBC_HDRGEN_ONLY; there is no need to have a distinct build step for
old
  hdrgen.
- libc-api-test and libc-api-test-tidy build targets.
- Deletes all .td files.

It does not rename newhdrgen to just hdrgen. Will follow up with a
distinct PR
for that.

Link: #117209
Link: #117254
Fixes: #117208
This commit is contained in:
Nick Desaulniers 2024-12-03 12:34:26 -08:00 committed by GitHub
parent fdd09e9de5
commit e0ae7793fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 50 additions and 6942 deletions

View File

@ -50,52 +50,27 @@ set(LIBC_NAMESPACE ${default_namespace}
CACHE STRING "The namespace to use to enclose internal implementations. Must start with '__llvm_libc'."
)
add_subdirectory(newhdrgen)
if(LLVM_LIBC_FULL_BUILD OR LLVM_LIBC_GPU_BUILD)
if(NOT LIBC_HDRGEN_EXE)
# We need to set up hdrgen first since other targets depend on it.
add_subdirectory(utils/LibcTableGenUtil)
add_subdirectory(utils/HdrGen)
# Calling add_tablegen sets variables like LIBC_TABLEGEN_EXE in
# PARENT_SCOPE which get lost until saved in the cache.
set(LIBC_TABLEGEN_EXE "${LIBC_TABLEGEN_EXE}" CACHE INTERNAL "")
set(LIBC_TABLEGEN_TARGET "${LIBC_TABLEGEN_TARGET}" CACHE INTERNAL "")
else()
message(STATUS "Will use ${LIBC_HDRGEN_EXE} for libc header generation.")
endif()
endif()
# We will build the GPU utilities if we are not doing a runtimes build.
option(LIBC_BUILD_GPU_LOADER "Always build the GPU loader utilities" OFF)
if(LIBC_BUILD_GPU_LOADER OR (LLVM_LIBC_GPU_BUILD AND NOT LLVM_RUNTIMES_BUILD))
add_subdirectory(utils/gpu)
endif()
option(LIBC_USE_NEW_HEADER_GEN "Generate header files using new headergen instead of the old one" ON)
set(NEED_LIBC_HDRGEN FALSE)
if(NOT LLVM_RUNTIMES_BUILD)
if("libc" IN_LIST LLVM_ENABLE_RUNTIMES)
set(NEED_LIBC_HDRGEN TRUE)
else()
foreach(_name ${LLVM_RUNTIME_TARGETS})
if("libc" IN_LIST RUNTIMES_${_name}_LLVM_ENABLE_RUNTIMES)
set(NEED_LIBC_HDRGEN TRUE)
break()
if(LIBC_BUILD_GPU_LOADER OR NOT LLVM_RUNTIMES_BUILD)
foreach(_name ${LLVM_RUNTIME_TARGETS})
if("libc" IN_LIST RUNTIMES_${_name}_LLVM_ENABLE_RUNTIMES)
if("${_name}" STREQUAL "amdgcn-amd-amdhsa" OR "${_name}" STREQUAL "nvptx64-nvidia-cuda")
set(LIBC_NEED_LOADER_UTILS TRUE)
endif()
endforeach()
endif()
endforeach()
if("${LIBC_TARGET_TRIPLE}" STREQUAL "amdgcn-amd-amdhsa" OR
"${LIBC_TARGET_TRIPLE}" STREQUAL "nvptx64-nvidia-cuda")
set(LIBC_NEED_LOADER_UTILS TRUE)
endif()
if(LIBC_NEED_LOADER_UTILS)
add_subdirectory(utils/gpu)
return()
endif()
endif()
option(LIBC_HDRGEN_ONLY "Only build the 'libc-hdrgen' executable" OFF)
if(LIBC_HDRGEN_ONLY OR NEED_LIBC_HDRGEN)
# When libc is build as part of the runtimes/bootstrap build's CMake run, we
# only need to build the host tools to build the libc. So, we just do enough
# to build libc-hdrgen and return.
return()
endif()
unset(NEED_LIBC_HDRGEN)
add_subdirectory(newhdrgen)
option(LIBC_CMAKE_VERBOSE_LOGGING
"Log details warnings and notifications during CMake configuration." OFF)

View File

@ -71,9 +71,9 @@ function(add_header target_name)
)
endfunction(add_header)
function(add_gen_header2 target_name)
function(add_gen_header target_name)
cmake_parse_arguments(
"ADD_GEN_HDR2"
"ADD_GEN_HDR"
"PUBLIC" # No optional arguments
"YAML_FILE;DEF_FILE;GEN_HDR" # Single value arguments
"DEPENDS" # Multi value arguments
@ -84,25 +84,25 @@ function(add_gen_header2 target_name)
add_library(${fq_target_name} INTERFACE)
return()
endif()
if(NOT ADD_GEN_HDR2_DEF_FILE)
message(FATAL_ERROR "`add_gen_hdr2` rule requires DEF_FILE to be specified.")
if(NOT ADD_GEN_HDR_DEF_FILE)
message(FATAL_ERROR "`add_gen_hdr` rule requires DEF_FILE to be specified.")
endif()
if(NOT ADD_GEN_HDR2_GEN_HDR)
message(FATAL_ERROR "`add_gen_hdr2` rule requires GEN_HDR to be specified.")
if(NOT ADD_GEN_HDR_GEN_HDR)
message(FATAL_ERROR "`add_gen_hdr` rule requires GEN_HDR to be specified.")
endif()
if(NOT ADD_GEN_HDR2_YAML_FILE)
message(FATAL_ERROR "`add_gen_hdr2` rule requires YAML_FILE to be specified.")
if(NOT ADD_GEN_HDR_YAML_FILE)
message(FATAL_ERROR "`add_gen_hdr` rule requires YAML_FILE to be specified.")
endif()
set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR2_GEN_HDR})
set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_GEN_HDR})
file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
set(yaml_file ${CMAKE_SOURCE_DIR}/${ADD_GEN_HDR2_YAML_FILE})
set(def_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR2_DEF_FILE})
set(yaml_file ${CMAKE_SOURCE_DIR}/${ADD_GEN_HDR_YAML_FILE})
set(def_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_DEF_FILE})
set(fq_data_files "")
if(ADD_GEN_HDR2_DATA_FILES)
foreach(data_file IN LISTS ADD_GEN_HDR2_DATA_FILES)
if(ADD_GEN_HDR_DATA_FILES)
foreach(data_file IN LISTS ADD_GEN_HDR_DATA_FILES)
list(APPEND fq_data_files "${CMAKE_CURRENT_SOURCE_DIR}/${data_file}")
endforeach(data_file)
endif()
@ -118,7 +118,7 @@ function(add_gen_header2 target_name)
${entry_points}
--output_dir ${out_file}
DEPENDS ${yaml_file} ${def_file} ${fq_data_files}
COMMENT "Generating header ${ADD_GEN_HDR2_GEN_HDR} from ${yaml_file} and ${def_file}"
COMMENT "Generating header ${ADD_GEN_HDR_GEN_HDR} from ${yaml_file} and ${def_file}"
)
if(LIBC_TARGET_OS_IS_GPU)
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls)
@ -136,132 +136,6 @@ function(add_gen_header2 target_name)
)
endif()
if(ADD_GEN_HDR2_DEPENDS)
get_fq_deps_list(fq_deps_list ${ADD_GEN_HDR2_DEPENDS})
# Dependencies of a add_header target can only be another add_gen_header target
# or an add_header target.
foreach(dep IN LISTS fq_deps_list)
get_target_property(header_file ${dep} HEADER_FILE_PATH)
if(NOT header_file)
message(FATAL_ERROR "Invalid dependency '${dep}' for '${fq_target_name}'.")
endif()
endforeach()
endif()
set(generated_hdr_target ${fq_target_name}.__generated_hdr__)
add_custom_target(
${generated_hdr_target}
DEPENDS ${out_file} ${fq_deps_list} ${decl_out_file}
)
add_header_library(
${target_name}
HDRS
${out_file}
)
add_dependencies(${fq_target_name} ${generated_hdr_target})
set_target_properties(
${fq_target_name}
PROPERTIES
HEADER_FILE_PATH ${out_file}
DECLS_FILE_PATH "${decl_out_file}"
DEPS "${fq_deps_list}"
)
endfunction(add_gen_header2)
# Usage:
# add_gen_header(
# <target name>
# DEF_FILE <.h.def file>
# GEN_HDR <generated header file name>
# PARAMS <list of name=value pairs>
# DATA_FILES <list input data files>
# )
function(add_gen_header target_name)
cmake_parse_arguments(
"ADD_GEN_HDR"
"PUBLIC" # No optional arguments
"DEF_FILE;GEN_HDR" # Single value arguments
"PARAMS;DATA_FILES;DEPENDS" # Multi value arguments
${ARGN}
)
get_fq_target_name(${target_name} fq_target_name)
if(NOT LLVM_LIBC_FULL_BUILD)
# We don't want to use generated headers if we are doing a non-full-build.
add_library(${fq_target_name} INTERFACE)
return()
endif()
if(NOT ADD_GEN_HDR_DEF_FILE)
message(FATAL_ERROR "`add_gen_hdr` rule requires DEF_FILE to be specified.")
endif()
if(NOT ADD_GEN_HDR_GEN_HDR)
message(FATAL_ERROR "`add_gen_hdr` rule requires GEN_HDR to be specified.")
endif()
set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_GEN_HDR})
file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
set(in_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_DEF_FILE})
set(fq_data_files "")
if(ADD_GEN_HDR_DATA_FILES)
foreach(data_file IN LISTS ADD_GEN_HDR_DATA_FILES)
list(APPEND fq_data_files "${CMAKE_CURRENT_SOURCE_DIR}/${data_file}")
endforeach(data_file)
endif()
set(replacement_params "")
if(ADD_GEN_HDR_PARAMS)
list(APPEND replacement_params "--args" ${ADD_GEN_HDR_PARAMS})
endif()
set(gen_hdr_script "${LIBC_BUILD_SCRIPTS_DIR}/gen_hdr.py")
file(GLOB td_includes ${LIBC_SOURCE_DIR}/spec/*.td)
set(ENTRYPOINT_NAME_LIST_ARG ${TARGET_ENTRYPOINT_NAME_LIST})
list(TRANSFORM ENTRYPOINT_NAME_LIST_ARG PREPEND "--e=")
if(LIBC_HDRGEN_EXE)
set(hdrgen_exe ${LIBC_HDRGEN_EXE})
else()
set(hdrgen_exe ${LIBC_TABLEGEN_EXE})
set(hdrgen_deps "${LIBC_TABLEGEN_EXE};${LIBC_TABLEGEN_TARGET}")
endif()
add_custom_command(
OUTPUT ${out_file}
COMMAND ${hdrgen_exe} -o ${out_file} --header ${ADD_GEN_HDR_GEN_HDR}
--def ${in_file} ${replacement_params} -I ${LIBC_SOURCE_DIR}
${ENTRYPOINT_NAME_LIST_ARG}
${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${in_file} ${fq_data_files} ${td_includes}
${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
${hdrgen_deps}
)
if(LIBC_TARGET_OS_IS_GPU)
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls)
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls/gpu)
set(decl_out_file ${LIBC_INCLUDE_DIR}/llvm-libc-decls/${relative_path})
add_custom_command(
OUTPUT ${decl_out_file}
COMMAND ${hdrgen_exe} -o ${decl_out_file}
--header ${ADD_GEN_HDR_GEN_HDR} --def ${in_file} --export-decls
${replacement_params} -I ${LIBC_SOURCE_DIR} ${ENTRYPOINT_NAME_LIST_ARG}
${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${in_file} ${fq_data_files} ${td_includes}
${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
${hdrgen_deps}
)
endif()
if(ADD_GEN_HDR_DEPENDS)
get_fq_deps_list(fq_deps_list ${ADD_GEN_HDR_DEPENDS})
# Dependencies of a add_header target can only be another add_gen_header target
@ -285,9 +159,6 @@ function(add_gen_header target_name)
${out_file}
)
# We add the dependencies separately and not list under add_header_library's
# DEPENDS option above. This is because, deps of add_header_library are
# used with target_link_libraries.
add_dependencies(${fq_target_name} ${generated_hdr_target})
set_target_properties(
@ -297,4 +168,6 @@ function(add_gen_header target_name)
DECLS_FILE_PATH "${decl_out_file}"
DEPS "${fq_deps_list}"
)
endfunction(add_gen_header)

View File

@ -1,59 +0,0 @@
include "config/public_api.td"
include "spec/stdc.td"
include "spec/stdc_ext.td"
include "spec/bsd_ext.td"
include "spec/llvm_libc_stdfix_ext.td"
def CTypeAPI : PublicAPI<"ctype.h"> {
}
def FEnvAPI : PublicAPI<"fenv.h"> {
let Types = ["fenv_t", "fexcept_t"];
}
def IntTypesAPI : PublicAPI<"inttypes.h"> {
let Types = ["imaxdiv_t"];
}
def MathAPI : PublicAPI<"math.h"> {
let Types = ["double_t", "float_t"];
}
def StdIOAPI : PublicAPI<"stdio.h"> {
let Types = ["size_t"];
}
def StdlibAPI : PublicAPI<"stdlib.h"> {
let Types = [
"div_t",
"ldiv_t",
"lldiv_t",
"size_t",
"__bsearchcompare_t",
"__qsortcompare_t",
];
}
def StringAPI : PublicAPI<"string.h"> {
let Types = ["size_t"];
}
def TimeAPI : PublicAPI<"time.h"> {
let Types = [
"clock_t",
"time_t",
"struct tm",
"struct timespec",
];
}
def UCharAPI : PublicAPI<"uchar.h"> {
let Types = [
"mbstate_t",
"char8_t",
"char16_t",
"char32_t",
];
}

View File

@ -1,50 +0,0 @@
include "config/public_api.td"
include "spec/stdc.td"
include "spec/posix.td"
include "spec/gpu_ext.td"
include "spec/gnu_ext.td"
include "spec/stdc_ext.td"
include "spec/llvm_libc_ext.td"
def StringAPI : PublicAPI<"string.h"> {
let Types = ["size_t"];
}
def StdlibAPI : PublicAPI<"stdlib.h"> {
let Types = [
"div_t",
"ldiv_t",
"lldiv_t",
"size_t",
"__bsearchcompare_t",
"__qsortcompare_t",
"__qsortrcompare_t",
"__atexithandler_t",
];
}
def FenvAPI: PublicAPI<"fenv.h"> {
let Types = ["fenv_t"];
}
def StdIOAPI : PublicAPI<"stdio.h"> {
let Types = [
"FILE",
"off_t",
"size_t",
];
}
def IntTypesAPI : PublicAPI<"inttypes.h"> {
let Types = ["imaxdiv_t"];
}
def TimeAPI : PublicAPI<"time.h"> {
let Types = [
"clock_t",
"time_t",
"struct timespec",
];
}

View File

@ -1,276 +0,0 @@
include "config/public_api.td"
include "spec/stdc.td"
include "spec/posix.td"
include "spec/linux.td"
include "spec/gnu_ext.td"
include "spec/bsd_ext.td"
include "spec/stdc_ext.td"
include "spec/llvm_libc_ext.td"
include "spec/llvm_libc_stdfix_ext.td"
def CTypeAPI : PublicAPI<"ctype.h"> {
}
def FCntlAPI : PublicAPI<"fcntl.h"> {
let Types = [
"mode_t",
"off_t",
];
}
def IntTypesAPI : PublicAPI<"inttypes.h"> {
let Types = ["imaxdiv_t"];
}
def MathAPI : PublicAPI<"math.h"> {
let Types = ["double_t", "float_t", "float128"];
}
def FenvAPI: PublicAPI<"fenv.h"> {
let Types = ["fenv_t", "fexcept_t"];
}
def StringAPI : PublicAPI<"string.h"> {
let Types = ["size_t"];
}
def StdIOAPI : PublicAPI<"stdio.h"> {
let Macros = [
SimpleMacroDef<"stderr", "stderr">,
SimpleMacroDef<"stdin", "stdin">,
SimpleMacroDef<"stdout", "stdout">,
];
let Types = [
"FILE",
"cookie_io_functions_t",
"off_t",
"size_t",
];
}
def StdlibAPI : PublicAPI<"stdlib.h"> {
let Types = [
"div_t",
"ldiv_t",
"lldiv_t",
"size_t",
"__bsearchcompare_t",
"__qsortcompare_t",
"__qsortrcompare_t",
"__atexithandler_t",
];
}
def TimeAPI : PublicAPI<"time.h"> {
let Types = [
"clock_t",
"time_t",
"struct tm",
"struct timespec",
"struct timeval",
"clockid_t",
];
}
def SchedAPI : PublicAPI<"sched.h"> {
let Types = [
"pid_t",
"size_t",
"cpu_set_t",
"struct sched_param",
// Needed according to posix standard
"time_t",
"struct timespec",
];
}
def SysMManAPI : PublicAPI<"sys/mman.h"> {
let Types = ["off_t", "size_t", "mode_t"];
}
def SignalAPI : PublicAPI<"signal.h"> {
let Types = [
"sig_atomic_t",
"sigset_t",
"struct sigaction",
"union sigval",
"siginfo_t",
"stack_t",
"pid_t",
];
}
def ThreadsAPI : PublicAPI<"threads.h"> {
let Macros = [
SimpleMacroDef<"ONCE_FLAG_INIT", "{0}">,
];
let Types = [
"__call_once_func_t",
"once_flag",
"cnd_t",
"mtx_t",
"thrd_t",
"thrd_start_t",
"tss_t",
"tss_dtor_t",
];
let Enumerations = [
"mtx_plain",
"mtx_recursive",
"mtx_timed",
"thrd_timedout",
"thrd_success",
"thrd_busy",
"thrd_error",
"thrd_nomem",
];
}
def PThreadAPI : PublicAPI<"pthread.h"> {
let Types = [
"__atfork_callback_t",
"__pthread_once_func_t",
"__pthread_start_t",
"__pthread_tss_dtor_t",
"pthread_attr_t",
"pthread_condattr_t",
"pthread_key_t",
"pthread_mutex_t",
"pthread_mutexattr_t",
"pthread_once_t",
"pthread_rwlockattr_t",
"pthread_rwlock_t",
"pthread_spinlock_t",
"pthread_t",
];
}
def DirentAPI : PublicAPI<"dirent.h"> {
let Types = [
"ino_t",
"DIR",
"struct dirent",
];
}
def UniStdAPI : PublicAPI<"unistd.h"> {
let Types = ["__exec_argv_t", "__exec_envp_t", "off_t", "pid_t", "size_t",
"ssize_t", "uid_t", "__getoptargv_t"];
}
def WCharAPI : PublicAPI<"wchar.h"> {
let Types = [
"wchar_t",
"wint_t",
"size_t",
];
}
def UCharAPI : PublicAPI<"uchar.h"> {
let Types = [
"mbstate_t",
"char8_t",
"char16_t",
"char32_t",
];
}
def SysRandomAPI : PublicAPI<"sys/random.h"> {
let Types = ["size_t", "ssize_t"];
}
def SysSelectAPI : PublicAPI<"sys/select.h"> {
let Types = ["fd_set", "sigset_t", "suseconds_t", "time_t", "struct timespec",
"struct timeval"];
}
def SysSocketAPI : PublicAPI<"sys/socket.h"> {
let Types = [
"sa_family_t",
"socklen_t",
"struct sockaddr",
"struct sockaddr_un",
"struct msghdr",
"struct iovec",
"size_t",
"ssize_t",
];
}
def SysResourceAPI : PublicAPI<"sys/resource.h"> {
let Types = ["rlim_t", "struct rlimit"];
}
def SysStatAPI : PublicAPI<"sys/stat.h"> {
let Types = ["mode_t", "dev_t", "ino_t", "nlink_t", "uid_t", "gid_t", "off_t",
"struct timespec", "struct timeval", "blksize_t", "blkcnt_t",
"struct stat"];
}
def SysWaitAPI : PublicAPI<"sys/wait.h"> {
let Types = ["pid_t", "struct rusage", "siginfo_t"];
}
def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> {
let Types = ["off_t", "size_t", "ssize_t"];
}
def SysTypesAPI : PublicAPI<"sys/types.h"> {
let Types = [
"blkcnt_t",
"blksize_t",
"clockid_t",
"dev_t",
"gid_t",
"ino_t",
"mode_t",
"nlink_t",
"off_t",
"pid_t",
"pthread_attr_t",
"pthread_condattr_t",
"pthread_key_t",
"pthread_mutex_t",
"pthread_mutexattr_t",
"pthread_once_t",
"pthread_rwlockattr_t",
"pthread_rwlock_t",
"pthread_t",
"size_t",
"ssize_t",
"suseconds_t",
"time_t",
"uid_t"
];
}
def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> {
let Types = ["struct utsname"];
}
def SysEpollAPI : PublicAPI<"sys/epoll.h"> {
let Types = ["struct epoll_event", "struct epoll_data", "sigset_t", "struct timespec"];
}
def SpawnAPI : PublicAPI<"spawn.h"> {
let Types = ["mode_t", "pid_t", "posix_spawnattr_t", "posix_spawn_file_actions_t"];
}
def TermiosAPI : PublicAPI<"termios.h"> {
let Types = ["cc_t", "pid_t", "speed_t", "struct termios", "tcflag_t"];
}
def SetJmpAPI : PublicAPI<"setjmp.h"> {
let Types = ["jmp_buf"];
}
def SearchAPI : PublicAPI<"search.h"> {
let Types = ["ACTION", "ENTRY", "struct hsearch_data", "__lsearchcompare_t"];
}
def SysStatvfsAPI : PublicAPI<"sys/statvfs.h"> {
let Types = ["struct statvfs"];
}

View File

@ -1,26 +0,0 @@
include "spec/spec.td"
class MacroDef<string name> {
string Name = name;
string Defn = "";
}
class SimpleMacroDef<string name, string value> : MacroDef<name> {
let Defn = !strconcat("#define ", name, " ", value);
}
class MacroDefineIfNot<string name, string value> : MacroDef<name> {
let Defn = !strconcat("#ifndef ", name, "\n",
"#define " , name, " ", value, "\n",
"#endif // ", name);
}
class PublicAPI<string name> {
string HeaderName = name;
list<MacroDef> Macros = [];
list<string> Types = [];
list<string> Enumerations = [];
list<string> Structs = [];
list<string> Functions = [];
list<string> Objects = [];
}

View File

@ -38,9 +38,6 @@ Required Versions:
``build/projects/libc/include/sys``.
New Headergen is turned on by default, but if you want to use old Headergen,
you can include this statement when building: ``-DLIBC_USE_NEW_HEADER_GEN=OFF``
To add a function to the YAML files, you can either manually enter it in the
YAML file corresponding to the header it belongs to or add it through the
command line.

View File

@ -63,10 +63,6 @@ targeting the default host environment as well.
Runtimes cross build
--------------------
.. note::
These instructions need to be updated for new headergen. They may be
inaccurate.
For users wanting more direct control over the build process, the build steps
can be done manually instead. This build closely follows the instructions in the
:ref:`main documentation<full_cross_build>` but is specialized for the GPU
@ -82,20 +78,17 @@ compiler. These tools must all be up-to-date with the libc source.
$> HOST_CXX_COMPILER=<C++ compiler for the host> # For example "clang++"
$> cmake ../llvm \
-G Ninja \
-DLLVM_ENABLE_PROJECTS="clang;libc" \
-DLLVM_ENABLE_PROJECTS="clang" \
-DCMAKE_C_COMPILER=$HOST_C_COMPILER \
-DCMAKE_CXX_COMPILER=$HOST_CXX_COMPILER \
-DLLVM_LIBC_FULL_BUILD=ON \
-DLIBC_HDRGEN_ONLY=ON \ # Only build the 'libc-hdrgen' tool
-DCMAKE_BUILD_TYPE=Release # Release suggested to make "clang" fast
$> ninja # Build the 'clang' compiler
$> ninja libc-hdrgen # Build the 'libc-hdrgen' tool
Once this has finished the build directory should contain the ``clang`` compiler
and the ``libc-hdrgen`` executable. We will use the ``clang`` compiler to build
the GPU code and the ``libc-hdrgen`` tool to create the necessary headers. We
use these tools to bootstrap the build out of the runtimes directory targeting a
GPU architecture.
Once this has finished the build directory should contain the ``clang``
compiler executable. We will use the ``clang`` compiler to build the GPU code.
We use these tools to bootstrap the build out of the runtimes directory
targeting a GPU architecture.
.. code-block:: sh
@ -105,7 +98,6 @@ GPU architecture.
$> TARGET_TRIPLE=<amdgcn-amd-amdhsa or nvptx64-nvidia-cuda>
$> TARGET_C_COMPILER=</path/to/clang>
$> TARGET_CXX_COMPILER=</path/to/clang++>
$> HDRGEN=</path/to/libc-hdrgen>
$> cmake ../runtimes \ # Point to the runtimes build
-G Ninja \
-DLLVM_ENABLE_RUNTIMES=libc \
@ -113,7 +105,6 @@ GPU architecture.
-DCMAKE_CXX_COMPILER=$TARGET_CXX_COMPILER \
-DLLVM_LIBC_FULL_BUILD=ON \
-DLLVM_RUNTIMES_TARGET=$TARGET_TRIPLE \
-DLIBC_HDRGEN_EXE=$HDRGEN \
-DCMAKE_BUILD_TYPE=Release
$> ninja install

View File

@ -17,25 +17,17 @@ add_header(
__llvm-libc-common.h
)
# TODO: Can we simplify this macro expansion?
# https://github.com/llvm/llvm-project/issues/117254
macro(add_header_macro TARGET_NAME YAML_FILE DEF_FILE GEN_HDR DEPENDS)
if (LIBC_USE_NEW_HEADER_GEN)
add_gen_header2(
${TARGET_NAME}
YAML_FILE ${YAML_FILE}
DEF_FILE ${DEF_FILE}
GEN_HDR ${GEN_HDR}
${DEPENDS}
${ARGN}
)
else()
add_gen_header(
${TARGET_NAME}
DEF_FILE ${DEF_FILE}
GEN_HDR ${GEN_HDR}
${DEPENDS}
${ARGN}
)
endif()
add_gen_header(
${TARGET_NAME}
YAML_FILE ${YAML_FILE}
DEF_FILE ${DEF_FILE}
GEN_HDR ${GEN_HDR}
${DEPENDS}
${ARGN}
)
endmacro()
add_header_macro(

View File

@ -1,87 +0,0 @@
def BsdExtensions : StandardSpec<"BSDExtensions"> {
HeaderSpec Math = HeaderSpec<
"math.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<"isnan", RetValSpec<IntType>, [ArgSpec<DoubleType>]>,
FunctionSpec<"isnanf", RetValSpec<IntType>, [ArgSpec<FloatType>]>,
FunctionSpec<"isnanl", RetValSpec<IntType>, [ArgSpec<LongDoubleType>]>,
]
>;
HeaderSpec String = HeaderSpec<
"string.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"strlcat",
RetValSpec<SizeTType>,
[ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"strlcpy",
RetValSpec<SizeTType>,
[ArgSpec<CharRestrictedPtr>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"strsep",
RetValSpec<CharPtr>,
[ArgSpec<CharRestrictedPtrPtr>, ArgSpec<ConstCharRestrictedPtr>]
>,
]
>;
HeaderSpec Strings = HeaderSpec<
"strings.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"strcasecmp",
RetValSpec<IntType>,
[ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
>,
FunctionSpec<
"strncasecmp",
RetValSpec<IntType>,
[ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"index",
RetValSpec<CharPtr>,
[ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
>,
FunctionSpec<
"rindex",
RetValSpec<CharPtr>,
[ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
>,
]
>;
HeaderSpec SysWait = HeaderSpec<
"sys/wait.h",
[], // Macros
[StructRUsage], // Types
[], // Enumerations
[
FunctionSpec<
"wait4",
RetValSpec<PidT>,
[ArgSpec<PidT>, ArgSpec<IntPtr>, ArgSpec<IntType>, ArgSpec<StructRUsagePtr>]
>
]
>;
let Headers = [
Math,
String,
Strings,
SysWait,
];
}

View File

@ -1,316 +0,0 @@
def CpuSetT : NamedType<"cpu_set_t">;
def CpuSetPtr : PtrType<CpuSetT>;
def ConstCpuSetPtr : ConstType<CpuSetPtr>;
def QSortRCompareT : NamedType<"__qsortrcompare_t">;
def StructHsearchData : NamedType<"struct hsearch_data">;
def StructHsearchDataPtr : PtrType<StructHsearchData>;
def GnuExtensions : StandardSpec<"GNUExtensions"> {
NamedType CookieIOFunctionsT = NamedType<"cookie_io_functions_t">;
HeaderSpec CType = HeaderSpec<
"ctype.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"toascii",
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
]
>;
HeaderSpec Malloc = HeaderSpec<
"malloc.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<"mallopt", RetValSpec<IntType>, [ArgSpec<IntType>, ArgSpec<IntType>]>,
]
>;
HeaderSpec Math = HeaderSpec<
"math.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"sincosf",
RetValSpec<VoidType>,
[ArgSpec<FloatType>, ArgSpec<FloatPtr>, ArgSpec<FloatPtr>]
>,
FunctionSpec<
"lgamma_r",
RetValSpec<DoubleType>,
[ArgSpec<DoubleType>, ArgSpec<IntPtr>]
>,
FunctionSpec<
"lgammaf_r",
RetValSpec<FloatType>,
[ArgSpec<FloatType>, ArgSpec<IntPtr>]
>,
FunctionSpec<
"lgammal_r",
RetValSpec<LongDoubleType>,
[ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]
>,
]
>;
HeaderSpec Sched = HeaderSpec<
"sched.h",
[], // Macros
[PidT, SizeTType, CpuSetT], // Types
[], // Enumerations
[
FunctionSpec<
"sched_getaffinity",
RetValSpec<IntType>,
[ArgSpec<PidT>, ArgSpec<SizeTType>, ArgSpec<CpuSetPtr>]
>,
FunctionSpec<
"sched_setaffinity",
RetValSpec<IntType>,
[ArgSpec<PidT>, ArgSpec<SizeTType>, ArgSpec<ConstCpuSetPtr>]
>,
]
>;
HeaderSpec String = HeaderSpec<
"string.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"memmem",
RetValSpec<VoidPtr>,
[ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"memrchr",
RetValSpec<VoidPtr>,
[ArgSpec<ConstVoidPtr>, ArgSpec<IntType>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"strerror_r",
RetValSpec<CharPtr>,
[ArgSpec<IntType>, ArgSpec<CharPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"strcasestr",
RetValSpec<CharPtr>,
[ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
>,
FunctionSpec<
"strchrnul",
RetValSpec<CharPtr>,
[ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
>,
]
>;
HeaderSpec Search = HeaderSpec<
"search.h",
[], // Macros
[
StructHsearchData
],
[], // Enumerations
[
FunctionSpec<
"hcreate_r",
RetValSpec<IntType>,
[
ArgSpec<SizeTType>,
ArgSpec<StructHsearchDataPtr>
]
>,
FunctionSpec<
"hdestroy_r",
RetValSpec<VoidType>,
[
ArgSpec<StructHsearchDataPtr>
]
>,
FunctionSpec<
"hsearch_r",
RetValSpec<IntType>,
[
ArgSpec<EntryType>,
ArgSpec<ActionType>,
ArgSpec<EntryTypePtrPtr>,
ArgSpec<StructHsearchDataPtr>
]
>,
]
>;
HeaderSpec FEnv = HeaderSpec<
"fenv.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"fedisableexcept",
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
FunctionSpec<
"feenableexcept",
RetValSpec<IntType>,
[ArgSpec<IntType>]
>,
FunctionSpec<
"fegetexcept",
RetValSpec<IntType>,
[]
>
]
>;
HeaderSpec StdIO = HeaderSpec<
"stdio.h",
[], // Macros
[CookieIOFunctionsT], // Types
[], // Enumerations
[
FunctionSpec<
"clearerr_unlocked",
RetValSpec<VoidType>,
[ArgSpec<FILEPtr>]
>,
FunctionSpec<
"feof_unlocked",
RetValSpec<IntType>,
[ArgSpec<FILEPtr>]
>,
FunctionSpec<
"ferror_unlocked",
RetValSpec<IntType>,
[ArgSpec<FILEPtr>]
>,
FunctionSpec<
"fopencookie",
RetValSpec<FILEPtr>,
[ArgSpec<VoidPtr>, ArgSpec<ConstCharPtr>, ArgSpec<CookieIOFunctionsT>]
>,
FunctionSpec<
"fread_unlocked",
RetValSpec<SizeTType>,
[ArgSpec<VoidRestrictedPtr>,
ArgSpec<SizeTType>,
ArgSpec<SizeTType>,
ArgSpec<FILERestrictedPtr>]
>,
FunctionSpec<
"fwrite_unlocked",
RetValSpec<SizeTType>,
[ArgSpec<ConstVoidRestrictedPtr>,
ArgSpec<SizeTType>,
ArgSpec<SizeTType>,
ArgSpec<FILERestrictedPtr>]
>,
FunctionSpec<
"fgetc_unlocked",
RetValSpec<IntType>,
[ArgSpec<FILEPtr>]
>,
]
>;
HeaderSpec StdLib = HeaderSpec<
"stdlib.h",
[], // Macros
[QSortRCompareT], // Types
[], // Enumerations
[
FunctionSpec<
"qsort_r",
RetValSpec<VoidType>,
[ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<QSortRCompareT>, ArgSpec<VoidPtr>]
>,
]
>;
HeaderSpec PThread = HeaderSpec<
"pthread.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"pthread_setname_np",
RetValSpec<IntType>,
[ArgSpec<PThreadTType>, ArgSpec<ConstCharPtr>]
>,
FunctionSpec<
"pthread_getname_np",
RetValSpec<IntType>,
[ArgSpec<PThreadTType>, ArgSpec<CharPtr>, ArgSpec<SizeTType>]
>,
]
>;
HeaderSpec SysAuxv = HeaderSpec<
"sys/auxv.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"getauxval",
RetValSpec<UnsignedLongType>,
[ArgSpec<UnsignedLongType>]
>,
] // Functions
>;
HeaderSpec SendFile = HeaderSpec<
"sys/sendfile.h",
[], // Macros
[OffTType, SizeTType, SSizeTType,], // Types
[], // Enumerations
[
FunctionSpec<
"sendfile",
RetValSpec<SSizeTType>,
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<OffTPtr>, ArgSpec<SizeTType>]
>,
]
>;
HeaderSpec UniStd = HeaderSpec<
"unistd.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"dup2",
RetValSpec<IntType>,
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntType>]
>,
]
>;
let Headers = [
CType,
FEnv,
Malloc,
Math,
PThread,
Sched,
SendFile,
SysAuxv,
StdIO,
StdLib,
String,
Search,
UniStd,
];
}

View File

@ -1,18 +0,0 @@
def GPUExtensions : StandardSpec<"GPUExtensions"> {
HeaderSpec RPC = HeaderSpec<
"gpu/rpc.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"rpc_host_call",
RetValSpec<UnsignedLongLongType>,
[ArgSpec<VoidPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
>,
]
>;
let Headers = [
RPC,
];
}

View File

@ -1,334 +0,0 @@
def StructEpollEvent : NamedType<"struct epoll_event">;
def StructEpollEventPtr : PtrType<StructEpollEvent>;
def StructEpollData : NamedType<"struct epoll_data">;
def Linux : StandardSpec<"Linux"> {
HeaderSpec Errno = HeaderSpec<
"errno.h",
[
Macro<"ENOMEDIUM">,
Macro<"ENOTBLK">,
Macro<"EMEDIUMTYPE">,
Macro<"EBADSLT">,
Macro<"ECHRNG">,
Macro<"ERFKILL">,
Macro<"EUSERS">,
Macro<"EBADR">,
Macro<"EL3HLT">,
Macro<"ENOTUNIQ">,
Macro<"EXFULL">,
Macro<"EHOSTDOWN">,
Macro<"EL3RST">,
Macro<"ENOPKG">,
Macro<"ENOCSI">,
Macro<"EUNATCH">,
Macro<"EREMCHG">,
Macro<"ETOOMANYREFS">,
Macro<"EL2HLT">,
Macro<"EBADFD">,
Macro<"EREMOTEIO">,
Macro<"ENAVAIL">,
Macro<"ELIBEXEC">,
Macro<"ESHUTDOWN">,
Macro<"ENOKEY">,
Macro<"ESTRPIPE">,
Macro<"EKEYREJECTED">,
Macro<"ESRMNT">,
Macro<"EKEYREVOKED">,
Macro<"EBADE">,
Macro<"ELIBBAD">,
Macro<"EISNAM">,
Macro<"EBFONT">,
Macro<"EPFNOSUPPORT">,
Macro<"EREMOTE">,
Macro<"EDEADLOCK">,
Macro<"ENONET">,
Macro<"EDOTDOT">,
Macro<"EKEYEXPIRED">,
Macro<"ELIBSCN">,
Macro<"ERESTART">,
Macro<"EBADRQC">,
Macro<"EUCLEAN">,
Macro<"ENOANO">,
Macro<"ELIBACC">,
Macro<"EHWPOISON">,
Macro<"ELIBMAX">,
Macro<"ESOCKTNOSUPPORT">,
Macro<"ENOTNAM">,
Macro<"ELNRNG">,
Macro<"EL2NSYNC">,
Macro<"EADV">,
Macro<"ECOMM">,
]
>;
HeaderSpec Sched = HeaderSpec<
"sched.h",
[
Macro<"SCHED_OTHER">,
Macro<"SCHED_FIFO">,
Macro<"SCHED_RR">,
Macro<"SCHED_BATCH">,
Macro<"SCHED_ISO">,
Macro<"SCHED_IDLE">,
Macro<"SCHED_DEADLINE">,
],
[], // Types
[], // Enumerations
[] // Functions
>;
HeaderSpec SysMMan = HeaderSpec<
"sys/mman.h",
[Macro<"MAP_ANONYMOUS">],
[], // Types
[], // Enumerations
[
FunctionSpec<
"mincore",
RetValSpec<IntType>,
[
ArgSpec<VoidPtr>,
ArgSpec<SizeTType>,
ArgSpec<UnsignedCharPtr>,
]
>,
FunctionSpec<
"mlock2",
RetValSpec<IntType>,
[
ArgSpec<VoidPtr>,
ArgSpec<SizeTType>,
ArgSpec<UnsignedIntType>,
]
>,
FunctionSpec<
"remap_file_pages",
RetValSpec<IntType>,
[
ArgSpec<VoidPtr>,
ArgSpec<SizeTType>,
ArgSpec<IntType>,
ArgSpec<SizeTType>,
ArgSpec<IntType>,
FunctionSpec<
"process_mrelease",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<UnsignedIntType>
]
>,
FunctionSpec<
"mremap",
RetValSpec<VoidPtr>,
[
ArgSpec<VoidPtr>,
ArgSpec<SizeTType>,
ArgSpec<SizeTType>,
ArgSpec<IntType>,
ArgSpec<VarArgType>,
]
>,
] // Functions
>;
HeaderSpec SysPrctl = HeaderSpec<
"sys/prctl.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"prctl",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<UnsignedLongType>,
ArgSpec<UnsignedLongType>,
ArgSpec<UnsignedLongType>,
ArgSpec<UnsignedLongType>,
]
>,
] // Functions
>;
HeaderSpec SysRandom = HeaderSpec<
"sys/random.h",
[
Macro<"GRND_RANDOM">,
Macro<"GRND_NONBLOCK">,
Macro<"GRND_INSECURE">,
],
[SizeTType, SSizeTType], // Types
[], // Enumerations
[
FunctionSpec<
"getrandom",
RetValSpec<SSizeTType>,
[
ArgSpec<VoidPtr>,
ArgSpec<SizeTType>,
ArgSpec<UnsignedIntType>
]
>,
]
>;
HeaderSpec SysTime = HeaderSpec<
"sys/time.h",
[
Macro<"timeradd">,
Macro<"timersub">,
Macro<"timerclear">,
Macro<"timerisset">,
Macro<"timercmp">,
],
[StructTimevalType], // Types
[], // Enumerations
[] // Functions
>;
HeaderSpec SysEpoll = HeaderSpec<
"sys/epoll.h",
[], // Macros
[
StructEpollEvent,
StructEpollData,
SigSetType,
StructTimeSpec,
], // Types
[], // Enumerations
[
FunctionSpec<
"epoll_create",
RetValSpec<IntType>,
[
ArgSpec<IntType>
]
>,
FunctionSpec<
"epoll_create1",
RetValSpec<IntType>,
[
ArgSpec<IntType>
]
>,
FunctionSpec<
"epoll_ctl",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<IntType>,
ArgSpec<IntType>,
ArgSpec<StructEpollEventPtr>
]
>,
FunctionSpec<
"epoll_wait",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<StructEpollEventPtr>,
ArgSpec<IntType>,
ArgSpec<IntType>
]
>,
FunctionSpec<
"epoll_pwait",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<StructEpollEventPtr>,
ArgSpec<IntType>,
ArgSpec<IntType>,
ArgSpec<ConstSigSetPtrType>
]
>,
FunctionSpec<
"epoll_pwait2",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<StructEpollEventPtr>,
ArgSpec<IntType>,
ArgSpec<ConstStructTimeSpecPtr>,
ArgSpec<ConstSigSetPtrType>
]
>,
] // Functions
>;
HeaderSpec Signal = HeaderSpec<
"signal.h",
[
Macro<"NSIG">,
Macro<"SIGHUP">,
Macro<"SIGINT">,
Macro<"SIGQUIT">,
Macro<"SIGILL">,
Macro<"SIGTRAP">,
Macro<"SIGABRT">,
Macro<"SIGIOT">,
Macro<"SIGBUS">,
Macro<"SIGFPE">,
Macro<"SIGKILL">,
Macro<"SIGUSR1">,
Macro<"SIGSEGV">,
Macro<"SIGUSR2">,
Macro<"SIGPIPE">,
Macro<"SIGALRM">,
Macro<"SIGTERM">,
Macro<"SIGSTKFLT">,
Macro<"SIGCHLD">,
Macro<"SIGCONT">,
Macro<"SIGSTOP">,
Macro<"SIGTSTP">,
Macro<"SIGTTIN">,
Macro<"SIGTTOU">,
Macro<"SIGURG">,
Macro<"SIGXCPU">,
Macro<"SIGXFSZ">,
Macro<"SIGVTALRM">,
Macro<"SIGPROF">,
Macro<"SIGWINCH">,
Macro<"SIGIO">,
Macro<"SIGPOLL">,
Macro<"SIGPWR">,
Macro<"SIGSYS">,
Macro<"SIGUNUSED">,
]
>;
HeaderSpec UniStd = HeaderSpec<
"unistd.h",
[], // Macros
[],
[], // Enumerations
[
FunctionSpec<
"pipe2",
RetValSpec<IntType>,
[ArgSpec<IntPtr>, ArgSpec<IntType>] //TODO: make this int[2]
>,
],
[]
>;
let Headers = [
Errno,
SysEpoll,
SysMMan,
SysPrctl,
SysRandom,
SysTime,
Signal,
UniStd,
];
}

View File

@ -1,116 +0,0 @@
def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
HeaderSpec Strings = HeaderSpec<
"strings.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"bcopy",
RetValSpec<VoidType>,
[ArgSpec<ConstVoidPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"bzero",
RetValSpec<VoidType>,
[ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
>,
FunctionSpec<
"bcmp",
RetValSpec<IntType>,
[ArgSpec<ConstVoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
>,
]
>;
HeaderSpec Assert = HeaderSpec<
"assert.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"__assert_fail",
RetValSpec<NoReturn>,
[ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<UnsignedType>, ArgSpec<ConstCharPtr>]
>,
]
>;
HeaderSpec Sched = HeaderSpec<
"sched.h",
[], // Macros
[PidT, SizeTType, CpuSetT], // Types
[], // Enumerations
[
FunctionSpec<
"__sched_getcpucount",
RetValSpec<IntType>,
[ArgSpec<SizeTType>, ArgSpec<ConstCpuSetPtr>]
>,
]
>;
HeaderSpec Math = HeaderSpec<
"math.h",
[], // Macros
[], // Types
[], // Enumerations
[
GuardedFunctionSpec<"daddf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"ddivf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"dfmaf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"dsqrtf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"dsubf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"f16add", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16addf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16addl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16sub", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16subf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16subl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"faddf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"fdivf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"ffmaf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"fmulf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"dmulf128", RetValSpec<DoubleType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"f16mul", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16mulf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16mull", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16div", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16divf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16divl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16fma", RetValSpec<Float16Type>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16fmaf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16fmal", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16sqrt", RetValSpec<Float16Type>, [ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16sqrtf", RetValSpec<Float16Type>, [ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"f16sqrtl", RetValSpec<Float16Type>, [ArgSpec<LongDoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"fsqrtf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
GuardedFunctionSpec<"fsubf128", RetValSpec<FloatType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"powi", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
FunctionSpec<"powif", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
]
>;
let Headers = [
Assert,
Math,
Sched,
Strings,
];
}

View File

@ -1,27 +0,0 @@
def LLVMLibcStdfixExt : StandardSpec<"llvm_libc_stdfix_ext"> {
HeaderSpec StdFix = HeaderSpec<
"stdfix.h",
[], // macros
[], // types
[], // enums
[ // functions
GuardedFunctionSpec<"exphk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"expk", RetValSpec<AccumType>, [ArgSpec<AccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"sqrtuhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"sqrtur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"sqrtulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"sqrtuhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"sqrtuk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"sqrtulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"uhksqrtus", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"uksqrtui", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedIntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
]
>;
let Headers = [
StdFix,
];
}

File diff suppressed because it is too large Load Diff

View File

@ -1,253 +0,0 @@
class Type {}
class NamedType<string name> : Type {
string Name = name;
}
class Field<string name, Type type> {
string Name = name;
Type FieldType = type;
}
// Class to describe concrete structs specified by a standard.
class Struct<string name> : NamedType<name> {
list<Field> Fields;
}
class EnumNameValue<string name, string value = "__default_enum_value__"> {
string Name = name;
string Value = value;
}
class Enum<string name, list<EnumNameValue> enumerations> : NamedType<name> {
list<EnumNameValue> Enumerations = enumerations;
}
class PtrType<Type type> : Type {
Type PointeeType = type;
}
class ConstType<Type type> : Type {
Type UnqualifiedType = type;
}
class RestrictedPtrType<Type type> : Type {
Type PointeeType = type;
}
// Builtin types.
def VarArgType : NamedType<"...">;
def VaListType : NamedType<"va_list">;
def VoidType : NamedType<"void">;
def IntType : NamedType<"int">;
def UnsignedIntType : NamedType<"unsigned int">;
def LongType : NamedType<"long">;
def UnsignedLongType : NamedType<"unsigned long">;
def LongLongType : NamedType<"long long">;
def UnsignedLongLongType : NamedType<"unsigned long long">;
def FloatType : NamedType<"float">;
def DoubleType : NamedType<"double">;
def LongDoubleType : NamedType<"long double">;
def CharType : NamedType<"char">;
def UnsignedCharType : NamedType<"unsigned char">;
def UnsignedShortType : NamedType<"unsigned short">;
def BoolType : NamedType<"bool">;
def Float16Type : NamedType<"_Float16">;
def Float128Type : NamedType<"float128">;
// Common types
def VoidPtr : PtrType<VoidType>;
def VoidPtrPtr : PtrType<VoidPtr>;
def RestrictedVoidPtrPtr : RestrictedPtrType<VoidPtr>;
def ConstVoidPtr : ConstType<VoidPtr>;
def SizeTType : NamedType<"size_t">;
def SizeTPtr : PtrType<SizeTType>;
def RestrictedSizeTPtr : RestrictedPtrType<SizeTType>;
def Char8TType : NamedType<"char8_t">;
def Char16TType : NamedType<"char16_t">;
def Char32TType : NamedType<"char32_t">;
def WCharType : NamedType<"wchar_t">;
def WIntType : NamedType<"wint_t">;
def LongDoublePtr : PtrType<LongDoubleType>;
def IntMaxTType : NamedType<"intmax_t">;
def UIntMaxTType : NamedType<"uintmax_t">;
def UInt16Type : NamedType<"uint16_t">;
def UInt32Type : NamedType<"uint32_t">;
def OffTType : NamedType<"off_t">;
def OffTPtr : PtrType<OffTType>;
def SSizeTType : NamedType<"ssize_t">;
// _Noreturn is really not a type, but it is convenient to treat it as a type.
def NoReturn : NamedType<"_Noreturn void">;
//types moved from stdc.td
def VoidRestrictedPtr : RestrictedPtrType<VoidType>;
def ConstVoidRestrictedPtr : ConstType<VoidRestrictedPtr>;
def CharPtr : PtrType<CharType>;
def ConstCharPtr : ConstType<CharPtr>;
def CharRestrictedPtr : RestrictedPtrType<CharType>;
def CharRestrictedPtrPtr : RestrictedPtrType<CharPtr>;
def ConstCharRestrictedPtr : ConstType<CharRestrictedPtr>;
def ConstCharRestrictedPtrPtr : PtrType<ConstCharRestrictedPtr>;
def OnceFlagType : NamedType<"once_flag">;
def OnceFlagTypePtr : PtrType<OnceFlagType>;
// TODO(sivachandra): Remove this non-standard type when a formal
// way to describe callable types is available.
def CallOnceFuncType : NamedType<"__call_once_func_t">;
def MtxTType : NamedType<"mtx_t">;
def MtxTTypePtr : PtrType<MtxTType>;
def CndTType : NamedType<"cnd_t">;
def CndTTypePtr : PtrType<CndTType>;
def ThrdStartTType : NamedType<"thrd_start_t">;
def ThrdTType : NamedType<"thrd_t">;
def ThrdTTypePtr : PtrType<ThrdTType>;
def IntPtr : PtrType<IntType>;
def RestrictedIntPtr : RestrictedPtrType<IntType>;
def FloatPtr : PtrType<FloatType>;
def DoublePtr : PtrType<DoubleType>;
def Float16Ptr : PtrType<Float16Type>;
def Float128Ptr : PtrType<Float128Type>;
def UnsignedCharPtr : PtrType<UnsignedCharType>;
def ConstDoublePtr : ConstType<DoublePtr>;
def ConstFloatPtr : ConstType<FloatPtr>;
def ConstLongDoublePtr : ConstType<LongDoublePtr>;
def ConstFloat16Ptr : ConstType<Float16Ptr>;
def ConstFloat128Ptr : ConstType<Float128Ptr>;
def SigHandlerT : NamedType<"__sighandler_t">;
def TimeTType : NamedType<"time_t">;
def StructTimeSpec : NamedType<"struct timespec">;
def StructTimeSpecPtr : PtrType<StructTimeSpec>;
def ConstStructTimeSpecPtr : ConstType<StructTimeSpecPtr>;
def RestrictStructTimeSpecPtr : RestrictedPtrType<StructTimeSpec>;
def ConstRestrictStructTimeSpecPtr : ConstType<RestrictStructTimeSpecPtr>;
def BSearchCompareT : NamedType<"__bsearchcompare_t">;
def QSortCompareT : NamedType<"__qsortcompare_t">;
def AtexitHandlerT : NamedType<"__atexithandler_t">;
def FILE : NamedType<"FILE">;
def FILEPtr : PtrType<FILE>;
def FILERestrictedPtr : RestrictedPtrType<FILE>;
def PThreadTType : NamedType<"pthread_t">;
def PidT : NamedType<"pid_t">;
def RestrictedPidTPtr : RestrictedPtrType<PidT>;
def StructRUsage : NamedType<"struct rusage">;
def StructRUsagePtr : PtrType<StructRUsage>;
def StructTimevalType : NamedType<"struct timeval">;
def StructTimevalPtr : PtrType<StructTimevalType>;
def RestrictedStructTimevalPtr : RestrictedPtrType<StructTimevalType>;
def SuSecondsT : NamedType<"suseconds_t">;
//added because __assert_fail needs it.
def UnsignedType : NamedType<"unsigned">;
def ActionType : NamedType<"ACTION">;
def EntryType : NamedType<"ENTRY">;
def EntryTypePtr : PtrType<EntryType>;
def EntryTypePtrPtr : PtrType<EntryTypePtr>;
def MBStateTType : NamedType<"mbstate_t">;
class Macro<string name> {
string Name = name;
}
class EnumeratedNameValue<string name, string value = "__default__"> {
string Name = name;
string Value = value;
}
class Annotation {}
class RetValSpec<Type type, list<Annotation> annotations = []> {
Type ReturnType = type;
list<Annotation> Annotations = annotations;
}
class ArgSpec<Type type, list<Annotation> annotations = [], string name = ""> {
Type ArgType = type;
list<Annotation> Annotations = annotations;
string Name = name;
}
// The following classes are used to describe function attributes.
// In the future, we may consider supporting parameter attributes as well.
// https://clang.llvm.org/docs/AttributeReference.html
class FunctionAttr<string style, string attr> {
string Attr = attr;
// The style of the attribute, e.g. "gnu", "cxx11", "declspec".
// - "gnu" is for GNU-style attributes: __attribute__((...))
// - "cxx11" is for C++11-style attributes: [[...]]
// - "declspec" is for Microsoft-style attributes: __declspec(...)
string Style = style;
// For the time being, we are only interested in identifer-like attributes.
// We can extend this to support function-like attributes if needed.
// For example, in the future, we can #define __LIBC_ATTRIBUTE_NODISCARD(...) [[nodiscard(__VA_ARGS__)]]
// int FunctionLike = 0;
}
class GnuFunctionAttr<string attr> : FunctionAttr<"gnu", attr> {}
class Cxx11FunctionAttr<string attr, string namespace> : FunctionAttr<"cxx11", attr> {
// The namespace of the attribute, e.g. "gnu" or "clang". Empty string means there is no namespace.
string Namespace = namespace;
}
class DeclspecFunctionAttr<string attr> : FunctionAttr<"declspec", attr> {}
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 GuardedFunctionSpec<string name, RetValSpec return, list<ArgSpec> args, string guard_macro> : FunctionSpec<name, return, args> {
string Guard = guard_macro;
}
class ObjectSpec<string name, string type> {
string Name = name;
string Type = type;
}
class HeaderSpec<string name,
list<Macro> macros = [],
list<Type> types = [],
list<EnumeratedNameValue> enumerations = [],
list<FunctionSpec> functions = [],
list<ObjectSpec> objects = []> {
string Name = name;
list<FunctionSpec> Functions = functions;
list<Type> Types = types;
list<Macro> Macros = macros;
list<EnumeratedNameValue> Enumerations = enumerations;
list<ObjectSpec> Objects = objects;
}
class StandardSpec<string name> {
string Name = name;
list<HeaderSpec> Headers;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
// Fixed point types.
// From ISO/IEC TR 18037:2008 standard:
// https://standards.iso.org/ittf/PubliclyAvailableStandards/c051126_ISO_IEC_TR_18037_2008.zip
def ShortFractType : NamedType<"short fract">;
def FractType : NamedType<"fract">;
def LongFractType : NamedType<"long fract">;
def UnsignedShortFractType : NamedType<"unsigned short fract">;
def UnsignedFractType : NamedType<"unsigned fract">;
def UnsignedLongFractType : NamedType<"unsigned long fract">;
def ShortAccumType : NamedType<"short accum">;
def AccumType : NamedType<"accum">;
def LongAccumType : NamedType<"long accum">;
def UnsignedShortAccumType : NamedType<"unsigned short accum">;
def UnsignedAccumType : NamedType<"unsigned accum">;
def UnsignedLongAccumType : NamedType<"unsigned long accum">;
def IntHrT : NamedType <"int_hr_t">;
def IntRT : NamedType<"int_r_t">;
def IntLrT : NamedType<"int_lr_t">;
def IntHkT : NamedType<"int_hk_t">;
def IntKT : NamedType<"int_k_t">;
def IntLkT : NamedType<"int_lk_t">;
def UIntUhrT : NamedType<"uint_uhr_t">;
def UIntUrT : NamedType<"uint_ur_t">;
def UIntUlrT : NamedType<"uint_ulr_t">;
def UIntUhkT : NamedType<"uint_uhk_t">;
def UIntUkT : NamedType<"uint_uk_t">;
def UIntUlkT : NamedType<"uint_ulk_t">;
def StdcExt : StandardSpec<"stdc_ext"> {
// From ISO/IEC TR 18037:2008 standard:
// https://standards.iso.org/ittf/PubliclyAvailableStandards/c051126_ISO_IEC_TR_18037_2008.zip
HeaderSpec StdFix = HeaderSpec<
"stdfix.h",
[], // macros
[IntHrT,IntRT, IntLrT, IntHkT, IntKT, IntLkT, UIntUhrT, UIntUrT, UIntUlrT, UIntUhkT, UIntUkT, UIntUlkT], // types
[], // enums
[ // functions
GuardedFunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"absr", RetValSpec<FractType>, [ArgSpec<FractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"abslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"abshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"absk", RetValSpec<AccumType>, [ArgSpec<AccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"abslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundhr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundlr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundhk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundlk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"rounduhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"rounduhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"rounduk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"roundulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"hrbits", RetValSpec<ShortFractType>, [ArgSpec<IntHrT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"rbits", RetValSpec<FractType>, [ArgSpec<IntRT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"lrbits", RetValSpec<LongFractType>, [ArgSpec<IntLrT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"hkbits", RetValSpec<ShortAccumType>, [ArgSpec<IntHkT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"kbits", RetValSpec<AccumType>, [ArgSpec<IntKT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"lkbits", RetValSpec<LongAccumType>, [ArgSpec<IntLkT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"uhrbits", RetValSpec<UnsignedShortFractType>, [ArgSpec<UIntUhrT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"urbits", RetValSpec<UnsignedFractType>, [ArgSpec<UIntUrT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"ukbits", RetValSpec<UnsignedAccumType>, [ArgSpec<UIntUkT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"ulrbits", RetValSpec<UnsignedLongFractType>, [ArgSpec<UIntUlrT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"uhkbits", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UIntUhkT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"ulkbits", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UIntUlkT>], "LIBC_COMPILER_HAS_FIXED_POINT">,
]
>;
let Headers = [
StdFix,
];
}

View File

@ -88,81 +88,3 @@ add_subdirectory(locale)
if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(pthread)
endif()
if(LLVM_RUNTIMES_BUILD OR LIBC_HDRGEN_EXE)
# The public API test below uses tablegen to generate the test
# source file. Since tablegen is not available during a runtimes
# build, we will skip the test.
# If a different libc-hdrgen binary is being used, then also we
# skip the api-test as we cannot generate the test source file.
return()
endif()
set(public_test ${CMAKE_CURRENT_BINARY_DIR}/public_api_test.cpp)
set(entrypoints_name_list "")
foreach(entry IN LISTS TARGET_LLVMLIBC_ENTRYPOINTS)
get_target_property(entry_name ${entry} "ENTRYPOINT_NAME")
list(APPEND entrypoints_name_list ${entry_name})
endforeach()
# TODO: Remove these when they are added to the TableGen.
list(REMOVE_ITEM entrypoints_name_list "__assert_fail" "__errno_location")
list(TRANSFORM entrypoints_name_list PREPEND "-e=")
file(GLOB spec_files ${LIBC_SOURCE_DIR}/spec/*.td)
# Generate api test souce code.
add_custom_command(
OUTPUT ${public_test}
COMMAND $<TARGET_FILE:libc-prototype-testgen> -o ${public_test}
${entrypoints_name_list}
-I ${LIBC_SOURCE_DIR}
${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
DEPENDS ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td ${spec_files}
libc-prototype-testgen ${TARGET_PUBLIC_HEADERS}
${LIBC_TARGET}
)
add_custom_target(libc-api-test)
add_dependencies(check-libc libc-api-test)
set(
allocator_entrypoints
libc.src.stdlib.malloc
libc.src.stdlib.calloc
libc.src.stdlib.realloc
libc.src.stdlib.aligned_alloc
libc.src.stdlib.free
)
set(api-test-entrypoints ${TARGET_LLVMLIBC_ENTRYPOINTS})
list(REMOVE_ITEM api-test-entrypoints ${allocator_entrypoints})
add_integration_test(
api-test
SUITE
libc-api-test
SRCS
${public_test}
DEPENDS
${api-test-entrypoints}
)
if(COMPILER_RESOURCE_DIR AND LLVM_LIBC_ENABLE_LINTING)
add_custom_target(
libc-api-test-tidy
VERBATIM
COMMAND ${LLVM_LIBC_CLANG_TIDY} --system-headers
--checks=-*,llvmlibc-restrict-system-libc-headers
"--extra-arg=-resource-dir=${COMPILER_RESOURCE_DIR}"
--header-filter=.*
--warnings-as-errors=llvmlibc-*
"-config={CheckOptions: [{key: llvmlibc-restrict-system-libc-headers.Includes, value: '-*, linux/*, asm/*.h, asm-generic/*.h'}]}"
--quiet
-p ${PROJECT_BINARY_DIR}
${public_test}
DEPENDS
clang-tidy ${public_test}
)
add_dependencies(libc-api-test libc-api-test-tidy)
endif()

View File

@ -1,22 +0,0 @@
include(TableGen)
if (NOT LLVM_LINK_LLVM_DYLIB)
set(LLVM_LINK_COMPONENTS Support)
endif()
add_tablegen(libc-hdrgen LIBC
Command.h
Command.cpp
Generator.cpp
Generator.h
IncludeFileCommand.cpp
IncludeFileCommand.h
Main.cpp
PublicAPICommand.cpp
PublicAPICommand.h
)
target_include_directories(libc-hdrgen PRIVATE ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR})
target_link_libraries(libc-hdrgen PRIVATE LibcTableGenUtil)
add_subdirectory(PrototypeTestGen)

View File

@ -1,15 +0,0 @@
//===-- Base class for header generation commands -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "Command.h"
namespace llvm_libc {
Command::~Command() {}
} // namespace llvm_libc

View File

@ -1,54 +0,0 @@
//===-- Base class for header generation commands ---------------*- C++ -*-===//
//
// 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_UTILS_HDRGEN_COMMAND_H
#define LLVM_LIBC_UTILS_HDRGEN_COMMAND_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/SourceMgr.h"
#include <cstdlib>
namespace llvm {
class raw_ostream;
class RecordKeeper;
} // namespace llvm
namespace llvm_libc {
typedef llvm::SmallVector<llvm::StringRef, 4> ArgVector;
class Command {
public:
class ErrorReporter {
llvm::SMLoc Loc;
const llvm::SourceMgr &SrcMgr;
public:
ErrorReporter(llvm::SMLoc L, llvm::SourceMgr &SM) : Loc(L), SrcMgr(SM) {}
[[noreturn]] void printFatalError(llvm::Twine Msg) const {
SrcMgr.PrintMessage(Loc, llvm::SourceMgr::DK_Error, Msg);
std::exit(1);
}
};
virtual ~Command();
virtual void run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader, const llvm::RecordKeeper &Records,
const ErrorReporter &Reporter) const = 0;
};
} // namespace llvm_libc
#endif // LLVM_LIBC_UTILS_HDRGEN_COMMAND_H

View File

@ -1,203 +0,0 @@
//===-- Implementation of the main header generation class ----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "Generator.h"
#include "IncludeFileCommand.h"
#include "PublicAPICommand.h"
#include "utils/LibcTableGenUtil/APIIndexer.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <memory>
static const char CommandPrefix[] = "%%";
static const size_t CommandPrefixSize = llvm::StringRef(CommandPrefix).size();
static const char CommentPrefix[] = "<!>";
static const char ParamNamePrefix[] = "${";
static const size_t ParamNamePrefixSize =
llvm::StringRef(ParamNamePrefix).size();
static const char ParamNameSuffix[] = "}";
static const size_t ParamNameSuffixSize =
llvm::StringRef(ParamNameSuffix).size();
namespace llvm_libc {
Command *Generator::getCommandHandler(llvm::StringRef CommandName) {
if (CommandName == IncludeFileCommand::Name) {
if (!IncludeFileCmd)
IncludeFileCmd = std::make_unique<IncludeFileCommand>();
return IncludeFileCmd.get();
} else if (CommandName == PublicAPICommand::Name) {
if (!PublicAPICmd)
PublicAPICmd = std::make_unique<PublicAPICommand>(EntrypointNameList);
return PublicAPICmd.get();
} else {
return nullptr;
}
}
void Generator::parseCommandArgs(llvm::StringRef ArgStr, ArgVector &Args) {
if (!ArgStr.contains(',') && ArgStr.trim(' ').trim('\t').size() == 0) {
// If it is just space between the parenthesis
return;
}
ArgStr.split(Args, ",");
for (llvm::StringRef &A : Args) {
A = A.trim(' ');
if (A.starts_with(ParamNamePrefix) && A.ends_with(ParamNameSuffix)) {
A = A.drop_front(ParamNamePrefixSize).drop_back(ParamNameSuffixSize);
A = ArgMap[std::string(A)];
}
}
}
void Generator::generate(llvm::raw_ostream &OS,
const llvm::RecordKeeper &Records) {
auto DefFileBuffer = llvm::MemoryBuffer::getFile(HeaderDefFile);
if (!DefFileBuffer) {
llvm::errs() << "Unable to open " << HeaderDefFile << ".\n";
std::exit(1);
}
llvm::SourceMgr SrcMgr;
unsigned DefFileID = SrcMgr.AddNewSourceBuffer(
std::move(DefFileBuffer.get()), llvm::SMLoc::getFromPointer(nullptr));
llvm::StringRef Content = SrcMgr.getMemoryBuffer(DefFileID)->getBuffer();
while (true) {
std::pair<llvm::StringRef, llvm::StringRef> P = Content.split('\n');
Content = P.second;
llvm::StringRef Line = P.first.trim(' ');
if (Line.starts_with(CommandPrefix)) {
Line = Line.drop_front(CommandPrefixSize);
P = Line.split("(");
// It's possible that we have windows line endings, so strip off the extra
// CR.
P.second = P.second.trim();
if (P.second.empty() || P.second[P.second.size() - 1] != ')') {
SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()),
llvm::SourceMgr::DK_Error,
"Command argument list should begin with '(' "
"and end with ')'.");
SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()),
llvm::SourceMgr::DK_Error, P.second.data());
SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()),
llvm::SourceMgr::DK_Error,
std::to_string(P.second.size()));
std::exit(1);
}
llvm::StringRef CommandName = P.first;
Command *Cmd = getCommandHandler(CommandName);
if (Cmd == nullptr) {
SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(CommandName.data()),
llvm::SourceMgr::DK_Error,
"Unknown command '%%" + CommandName + "'.");
std::exit(1);
}
llvm::StringRef ArgStr = P.second.drop_back(1);
ArgVector Args;
parseCommandArgs(ArgStr, Args);
Command::ErrorReporter Reporter(
llvm::SMLoc::getFromPointer(CommandName.data()), SrcMgr);
Cmd->run(OS, Args, StdHeader, Records, Reporter);
} else if (!Line.starts_with(CommentPrefix)) {
// There is no comment or command on this line so we just write it as is.
OS << P.first << "\n";
}
if (P.second.empty())
break;
}
}
void Generator::generateDecls(llvm::raw_ostream &OS,
const llvm::RecordKeeper &Records) {
OS << "//===-- C standard declarations for " << StdHeader << " "
<< std::string(80 - (42 + StdHeader.size()), '-') << "===//\n"
<< "//\n"
<< "// Part of the LLVM Project, under the Apache License v2.0 with LLVM "
"Exceptions.\n"
<< "// See https://llvm.org/LICENSE.txt for license information.\n"
<< "// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
<< "//\n"
<< "//"
"===-------------------------------------------------------------------"
"---===//\n\n";
std::string HeaderGuard(StdHeader.size(), '\0');
llvm::transform(StdHeader, HeaderGuard.begin(), [](const char C) -> char {
return !isalnum(C) ? '_' : llvm::toUpper(C);
});
OS << "#ifndef __LLVM_LIBC_DECLARATIONS_" << HeaderGuard << "\n"
<< "#define __LLVM_LIBC_DECLARATIONS_" << HeaderGuard << "\n\n";
OS << "#ifndef __LIBC_ATTRS\n"
<< "#define __LIBC_ATTRS\n"
<< "#endif\n\n";
OS << "#ifdef __cplusplus\n"
<< "extern \"C\" {\n"
<< "#endif\n\n";
APIIndexer G(StdHeader, Records);
for (auto &Name : EntrypointNameList) {
// Filter out functions not exported by this header.
if (G.FunctionSpecMap.find(Name) == G.FunctionSpecMap.end())
continue;
const llvm::Record *FunctionSpec = G.FunctionSpecMap[Name];
const llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
const llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
OS << G.getTypeAsString(ReturnType) << " " << Name << "(";
auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
for (size_t i = 0; i < ArgsList.size(); ++i) {
const llvm::Record *ArgType = ArgsList[i]->getValueAsDef("ArgType");
OS << G.getTypeAsString(ArgType);
if (i < ArgsList.size() - 1)
OS << ", ";
}
OS << ") __LIBC_ATTRS;\n\n";
}
// Make another pass over entrypoints to emit object declarations.
for (const auto &Name : EntrypointNameList) {
if (G.ObjectSpecMap.find(Name) == G.ObjectSpecMap.end())
continue;
const llvm::Record *ObjectSpec = G.ObjectSpecMap[Name];
auto Type = ObjectSpec->getValueAsString("Type");
OS << "extern " << Type << " " << Name << " __LIBC_ATTRS;\n";
}
// Emit a final newline if we emitted any object declarations.
if (llvm::any_of(EntrypointNameList, [&](const std::string &Name) {
return G.ObjectSpecMap.find(Name) != G.ObjectSpecMap.end();
}))
OS << "\n";
OS << "#ifdef __cplusplus\n"
<< "}\n"
<< "#endif\n\n";
OS << "#endif\n";
}
} // namespace llvm_libc

View File

@ -1,60 +0,0 @@
//===-- The main header generation class ------------------------*- C++ -*-===//
//
// 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_UTILS_HDRGEN_GENERATOR_H
#define LLVM_LIBC_UTILS_HDRGEN_GENERATOR_H
#include "Command.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <memory>
#include <string>
#include <unordered_map>
namespace llvm {
class raw_ostream;
class RecordKeeper;
} // namespace llvm
namespace llvm_libc {
class Command;
class Generator {
llvm::StringRef HeaderDefFile;
const std::vector<std::string> &EntrypointNameList;
llvm::StringRef StdHeader;
std::unordered_map<std::string, std::string> &ArgMap;
std::unique_ptr<Command> IncludeFileCmd;
std::unique_ptr<Command> PublicAPICmd;
Command *getCommandHandler(llvm::StringRef CommandName);
void parseCommandArgs(llvm::StringRef ArgStr, ArgVector &Args);
void printError(llvm::StringRef Msg);
public:
Generator(const std::string &DefFile, const std::vector<std::string> &EN,
const std::string &Header,
std::unordered_map<std::string, std::string> &Map)
: HeaderDefFile(DefFile), EntrypointNameList(EN), StdHeader(Header),
ArgMap(Map) {}
void generate(llvm::raw_ostream &OS, const llvm::RecordKeeper &Records);
void generateDecls(llvm::raw_ostream &OS, const llvm::RecordKeeper &Records);
};
} // namespace llvm_libc
#endif // LLVM_LIBC_UTILS_HDRGEN_GENERATOR_H

View File

@ -1,50 +0,0 @@
//===-- Implementation of IncludeFileCommand ------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "IncludeFileCommand.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include <cstdlib>
namespace llvm_libc {
const char IncludeFileCommand::Name[] = "include_file";
void IncludeFileCommand::run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader,
const llvm::RecordKeeper &Records,
const Command::ErrorReporter &Reporter) const {
if (Args.size() != 1) {
Reporter.printFatalError(
"%%include_file command takes exactly 1 argument.");
}
llvm::StringRef IncludeFile = Args[0];
auto Buffer = llvm::MemoryBuffer::getFileAsStream(IncludeFile);
if (!Buffer)
Reporter.printFatalError(llvm::StringRef("Unable to open ") + IncludeFile);
llvm::StringRef Content = Buffer.get()->getBuffer();
// If the included file has %%begin() command listed, then we want to write
// only the content after the begin command.
// TODO: The way the content is split below does not allow space within the
// the parentheses and, before and after the command. This probably is too
// strict and should be relaxed.
auto P = Content.split("\n%%begin()\n");
if (P.second.empty()) {
// There was no %%begin in the content.
OS << P.first;
} else {
OS << P.second;
}
}
} // namespace llvm_libc

View File

@ -1,32 +0,0 @@
//===-- Class which implements the %%include_file command -------*- C++ -*-===//
//
// 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_UTILS_HDRGEN_INCLUDE_COMMAND_H
#define LLVM_LIBC_UTILS_HDRGEN_INCLUDE_COMMAND_H
#include "Command.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <string>
namespace llvm_libc {
class IncludeFileCommand : public Command {
public:
static const char Name[];
void run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader, const llvm::RecordKeeper &Records,
const Command::ErrorReporter &Reporter) const override;
};
} // namespace llvm_libc
#endif // LLVM_LIBC_UTILS_HDRGEN_INCLUDE_COMMAND_H

View File

@ -1,62 +0,0 @@
//===-- "main" function of libc-hdrgen ------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "Generator.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/TableGen/Main.h"
#include <string>
#include <unordered_map>
static llvm::cl::opt<std::string>
HeaderDefFile("def", llvm::cl::desc("Path to the .h.def file."),
llvm::cl::value_desc("<filename>"), llvm::cl::Required);
static llvm::cl::opt<std::string> StandardHeader(
"header",
llvm::cl::desc("The standard header file which is to be generated."),
llvm::cl::value_desc("<header file>"));
static llvm::cl::list<std::string> EntrypointNamesOption(
"e", llvm::cl::value_desc("<list of entrypoints>"),
llvm::cl::desc(
"Each --e is one entrypoint (generated from entrypoints.txt)"),
llvm::cl::OneOrMore);
static llvm::cl::list<std::string> ReplacementValues(
"args", llvm::cl::desc("Command separated <argument name>=<value> pairs."),
llvm::cl::value_desc("<name=value>[,name=value]"));
static llvm::cl::opt<bool> ExportDecls(
"export-decls",
llvm::cl::desc("Output a new header containing only the entrypoints."));
static void
ParseArgValuePairs(std::unordered_map<std::string, std::string> &Map) {
for (std::string &R : ReplacementValues) {
auto Pair = llvm::StringRef(R).split('=');
Map[std::string(Pair.first)] = std::string(Pair.second);
}
}
static bool HeaderGeneratorMain(llvm::raw_ostream &OS,
const llvm::RecordKeeper &Records) {
std::unordered_map<std::string, std::string> ArgMap;
ParseArgValuePairs(ArgMap);
llvm_libc::Generator G(HeaderDefFile, EntrypointNamesOption, StandardHeader,
ArgMap);
if (ExportDecls)
G.generateDecls(OS, Records);
else
G.generate(OS, Records);
return false;
}
int main(int argc, char *argv[]) {
llvm::cl::ParseCommandLineOptions(argc, argv);
return TableGenMain(argv[0], &HeaderGeneratorMain);
}

View File

@ -1,5 +0,0 @@
add_tablegen(libc-prototype-testgen LLVM_LIBC
PrototypeTestGen.cpp
)
target_link_libraries(libc-prototype-testgen PRIVATE LibcTableGenUtil)
target_include_directories(libc-prototype-testgen PRIVATE ${LIBC_SOURCE_DIR})

View File

@ -1,106 +0,0 @@
//===-- PrototypeTestGen.cpp ----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "utils/LibcTableGenUtil/APIIndexer.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/TableGen/Main.h"
#include "llvm/TableGen/Record.h"
namespace {
llvm::cl::list<std::string>
EntrypointNamesOption("e", llvm::cl::desc("<list of entrypoints>"),
llvm::cl::OneOrMore);
} // anonymous namespace
bool TestGeneratorMain(llvm::raw_ostream &OS,
const llvm::RecordKeeper &records) {
OS << "#include \"src/__support/CPP/type_traits.h\"\n";
llvm_libc::APIIndexer G(records);
std::unordered_set<std::string> headerFileSet;
for (const auto &entrypoint : EntrypointNamesOption) {
if (entrypoint == "errno")
continue;
auto match = G.FunctionToHeaderMap.find(entrypoint);
if (match == G.FunctionToHeaderMap.end()) {
auto objectMatch = G.ObjectToHeaderMap.find(entrypoint);
if (objectMatch != G.ObjectToHeaderMap.end()) {
headerFileSet.insert(objectMatch->second);
continue;
}
llvm::errs() << "ERROR: entrypoint '" << entrypoint
<< "' could not be found in spec in any public header\n";
return true;
}
headerFileSet.insert(match->second);
}
for (const auto &header : headerFileSet)
OS << "#include <" << header << ">\n";
OS << '\n';
OS << "extern \"C\" int main() {\n";
for (const auto &entrypoint : EntrypointNamesOption) {
if (entrypoint == "errno")
continue;
auto match = G.FunctionSpecMap.find(entrypoint);
if (match == G.FunctionSpecMap.end()) {
auto objectMatch = G.ObjectSpecMap.find(entrypoint);
if (objectMatch != G.ObjectSpecMap.end()) {
auto entrypointPtr = entrypoint + "_ptr";
llvm::Record *objectSpec = G.ObjectSpecMap[entrypoint];
auto objectType = objectSpec->getValueAsString("Type");
// We just make sure that the global object is present.
OS << " " << objectType << " *" << entrypointPtr << " = &"
<< entrypoint << ";\n";
OS << " ++" << entrypointPtr << ";\n"; // To avoid unused var warning.
continue;
}
llvm::errs() << "ERROR: entrypoint '" << entrypoint
<< "' could not be found in spec in any public header\n";
return true;
}
llvm::Record *functionSpec = match->second;
llvm::Record *retValSpec = functionSpec->getValueAsDef("Return");
std::string returnType =
G.getTypeAsString(retValSpec->getValueAsDef("ReturnType"));
// _Noreturn is an indication for the compiler that a function
// doesn't return, and isn't a type understood by c++ templates.
if (llvm::StringRef(returnType).contains("_Noreturn"))
returnType = "void";
OS << " static_assert(LIBC_NAMESPACE::cpp::is_same_v<" << returnType
<< '(';
auto args = functionSpec->getValueAsListOfDefs("Args");
for (size_t i = 0, size = args.size(); i < size; ++i) {
llvm::Record *argType = args[i]->getValueAsDef("ArgType");
OS << G.getTypeAsString(argType);
if (i < size - 1)
OS << ", ";
}
OS << ") __NOEXCEPT, decltype(" << entrypoint << ")>, ";
OS << '"' << entrypoint
<< " prototype in TableGen does not match public header" << '"';
OS << ");\n";
}
OS << '\n';
OS << " return 0;\n";
OS << "}\n\n";
return false;
}
int main(int argc, char *argv[]) {
llvm::cl::ParseCommandLineOptions(argc, argv);
return TableGenMain(argv[0], TestGeneratorMain);
}

View File

@ -1,331 +0,0 @@
//===-- Implementation of PublicAPICommand --------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "PublicAPICommand.h"
#include "utils/LibcTableGenUtil/APIIndexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <vector>
// Text blocks for macro definitions and type decls can be indented to
// suit the surrounding tablegen listing. We need to dedent such blocks
// before writing them out.
static void dedentAndWrite(llvm::StringRef Text, llvm::raw_ostream &OS) {
llvm::SmallVector<llvm::StringRef, 10> Lines;
llvm::SplitString(Text, Lines, "\n");
size_t shortest_indent = 1024;
for (llvm::StringRef L : Lines) {
llvm::StringRef Indent = L.take_while([](char c) { return c == ' '; });
size_t IndentSize = Indent.size();
if (Indent.size() == L.size()) {
// Line is all spaces so no point noting the indent.
continue;
}
if (IndentSize < shortest_indent)
shortest_indent = IndentSize;
}
for (llvm::StringRef L : Lines) {
if (L.size() >= shortest_indent)
OS << L.drop_front(shortest_indent) << '\n';
}
}
static std::string getTypeHdrName(const std::string &Name) {
llvm::SmallVector<llvm::StringRef> Parts;
llvm::SplitString(llvm::StringRef(Name), Parts);
return llvm::join(Parts.begin(), Parts.end(), "_");
}
namespace llvm_libc {
static bool isAsciiStart(char C) {
return (C >= 'A' && C <= 'Z') || (C >= 'a' && C <= 'z') || C == '_';
}
static bool isAsciiContinue(char C) {
return isAsciiStart(C) || (C >= '0' && C <= '9');
}
static bool isAsciiIdentifier(llvm::StringRef S) {
if (S.empty())
return false;
if (!isAsciiStart(S[0]))
return false;
for (char C : S.drop_front())
if (!isAsciiContinue(C))
return false;
return true;
}
static AttributeStyle getAttributeStyle(const llvm::Record *Instance) {
llvm::StringRef Style = Instance->getValueAsString("Style");
return llvm::StringSwitch<AttributeStyle>(Style)
.Case("cxx11", AttributeStyle::Cxx11)
.Case("gnu", AttributeStyle::Gnu)
.Case("declspec", AttributeStyle::Declspec)
.Default(AttributeStyle::Gnu);
}
static AttributeNamespace getAttributeNamespace(const llvm::Record *Instance) {
llvm::StringRef Namespace = Instance->getValueAsString("Namespace");
return llvm::StringSwitch<AttributeNamespace>(Namespace)
.Case("clang", AttributeNamespace::Clang)
.Case("gnu", AttributeNamespace::Gnu)
.Default(AttributeNamespace::None);
}
using AttributeMap = llvm::DenseMap<llvm::StringRef, const llvm::Record *>;
template <class SpecMap, class FuncList>
static AttributeMap collectAttributeMacros(const SpecMap &Spec,
const FuncList &Funcs) {
llvm::DenseMap<llvm::StringRef, const llvm::Record *> MacroAttr;
for (const auto &Name : Funcs) {
auto Iter = Spec.find(Name);
if (Iter == Spec.end())
continue;
const llvm::Record *FunctionSpec = Iter->second;
for (const llvm::Record *Attr :
FunctionSpec->getValueAsListOfDefs("Attributes"))
MacroAttr[Attr->getValueAsString("Macro")] = Attr;
}
return MacroAttr;
}
static void emitAttributeMacroDecls(const AttributeMap &MacroAttr,
llvm::raw_ostream &OS) {
for (auto &[Macro, Attr] : MacroAttr) {
std::vector<const llvm::Record *> Instances =
Attr->getValueAsListOfDefs("Instances");
llvm::SmallVector<std::pair<AttributeStyle, const llvm::Record *>> Styles;
std::transform(Instances.begin(), Instances.end(),
std::back_inserter(Styles),
[&](const llvm::Record *Instance)
-> std::pair<AttributeStyle, const llvm::Record *> {
auto Style = getAttributeStyle(Instance);
return {Style, Instance};
});
// 1. If __cplusplus is defined and cxx11 style is provided, define the
// macro using cxx11 version with the following priority:
// 1a. If there is no namespace (so the macro is supposed to be
// compiler-independent), use this version first. This macro will be
// tested via __has_cpp_attribute.
// 1b. If the attribute is a clang attribute, check for __clang__.
// 1c. If the attribute is a gnu attribute, check for __GNUC__.
// 2. Otherwise, if __GNUC__ is defined and gnu style is provided,
// define the macro using gnu version;
// 3. Otherwise, if _MSC_VER is defined and __declspec is provided, define
// the macro using __declspec version;
// 4. Fallback to empty macro.
std::sort(Styles.begin(), Styles.end(), [&](auto &a, auto &b) {
if (a.first == AttributeStyle::Cxx11 && b.first == AttributeStyle::Cxx11)
return getAttributeNamespace(a.second) <
getAttributeNamespace(b.second);
return a.first < b.first;
});
for (auto &[Style, Instance] : Styles) {
llvm::StringRef Attr = Instance->getValueAsString("Attr");
if (Style == AttributeStyle::Cxx11) {
OS << "#if !defined(" << Macro << ") && defined(__cplusplus)";
AttributeNamespace Namespace = getAttributeNamespace(Instance);
if (Namespace == AttributeNamespace::Clang)
OS << " && defined(__clang__)\n";
else if (Namespace == AttributeNamespace::Gnu)
OS << " && defined(__GNUC__)\n";
else
OS << '\n';
if (isAsciiIdentifier(Attr) && Namespace != AttributeNamespace::None)
OS << "#if __has_attribute(" << Attr << ")\n";
else
OS << "#if __has_cpp_attribute(" << Attr << ")\n";
OS << "#define " << Macro << " [[";
if (Namespace == AttributeNamespace::Clang)
OS << "clang::";
else if (Namespace == AttributeNamespace::Gnu)
OS << "gnu::";
OS << Attr << "]]\n";
if (isAsciiIdentifier(Attr))
OS << "#endif\n";
OS << "#endif\n";
}
if (Style == AttributeStyle::Gnu) {
OS << "#if !defined(" << Macro << ") && defined(__GNUC__)\n";
if (isAsciiIdentifier(Attr))
OS << "#if __has_attribute(" << Attr << ")\n";
OS << "#define " << Macro << " __attribute__((";
OS << Attr << "))\n";
if (isAsciiIdentifier(Attr))
OS << "#endif\n";
OS << "#endif\n";
}
if (Style == AttributeStyle::Declspec) {
OS << "#if !defined(" << Macro << ") && defined(_MSC_VER)\n";
OS << "#define " << Macro << " __declspec(";
OS << Attr << ")\n";
OS << "#endif\n";
}
}
OS << "#if !defined(" << Macro << ")\n";
OS << "#define " << Macro << '\n';
OS << "#endif\n";
}
if (!MacroAttr.empty())
OS << '\n';
}
static void emitAttributeMacroForFunction(const llvm::Record *FunctionSpec,
llvm::raw_ostream &OS) {
std::vector<const llvm::Record *> Attributes =
FunctionSpec->getValueAsListOfDefs("Attributes");
llvm::interleave(
Attributes.begin(), Attributes.end(),
[&](const llvm::Record *Attr) { OS << Attr->getValueAsString("Macro"); },
[&]() { OS << ' '; });
if (!Attributes.empty())
OS << ' ';
}
static void emitUndefsForAttributeMacros(const AttributeMap &MacroAttr,
llvm::raw_ostream &OS) {
if (!MacroAttr.empty())
OS << '\n';
for (auto &[Macro, Attr] : MacroAttr)
OS << "#undef " << Macro << '\n';
}
static void writeAPIFromIndex(APIIndexer &G,
std::vector<std::string> EntrypointNameList,
llvm::raw_ostream &OS) {
for (auto &Pair : G.MacroDefsMap) {
const std::string &Name = Pair.first;
if (!G.MacroSpecMap.count(Name))
llvm::PrintFatalError(Name + " not found in any standard spec.\n");
const llvm::Record *MacroDef = Pair.second;
dedentAndWrite(MacroDef->getValueAsString("Defn"), OS);
OS << '\n';
}
for (auto &TypeName : G.RequiredTypes) {
if (!G.TypeSpecMap.count(TypeName))
llvm::PrintFatalError(TypeName + " not found in any standard spec.\n");
OS << "#include <llvm-libc-types/" << getTypeHdrName(TypeName) << ".h>\n";
}
OS << '\n';
if (G.Enumerations.size() != 0)
OS << "enum {" << '\n';
for (const auto &Name : G.Enumerations) {
if (!G.EnumerationSpecMap.count(Name))
llvm::PrintFatalError(
Name + " is not listed as an enumeration in any standard spec.\n");
const llvm::Record *EnumerationSpec = G.EnumerationSpecMap[Name];
OS << " " << EnumerationSpec->getValueAsString("Name");
auto Value = EnumerationSpec->getValueAsString("Value");
if (Value == "__default__") {
OS << ",\n";
} else {
OS << " = " << Value << ",\n";
}
}
if (G.Enumerations.size() != 0)
OS << "};\n\n";
// Collect and declare macros for attributes
AttributeMap MacroAttr =
collectAttributeMacros(G.FunctionSpecMap, EntrypointNameList);
emitAttributeMacroDecls(MacroAttr, OS);
OS << "__BEGIN_C_DECLS\n\n";
for (auto &Name : EntrypointNameList) {
auto Iter = G.FunctionSpecMap.find(Name);
// Functions that aren't in this header file are skipped as
// opposed to erroring out because the list of functions being
// iterated over is the complete list of functions with
// entrypoints. Thus this is filtering out the functions that
// don't go to this header file, whereas the other, similar
// conditionals above are more of a sanity check.
if (Iter == G.FunctionSpecMap.end())
continue;
const llvm::Record *FunctionSpec = Iter->second;
const llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
const llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
// TODO: https://github.com/llvm/llvm-project/issues/81208
// Ideally, we should group functions based on their guarding macros.
bool Guarded =
(FunctionSpec->getType()->getAsString() == "GuardedFunctionSpec");
if (Guarded)
OS << "#ifdef " << FunctionSpec->getValueAsString("Guard") << "\n";
// Emit attribute macros for the function. Space is automatically added.
emitAttributeMacroForFunction(FunctionSpec, OS);
OS << G.getTypeAsString(ReturnType) << " " << Name << "(";
auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
for (size_t i = 0; i < ArgsList.size(); ++i) {
const llvm::Record *ArgType = ArgsList[i]->getValueAsDef("ArgType");
OS << G.getTypeAsString(ArgType);
if (i < ArgsList.size() - 1)
OS << ", ";
}
OS << ") __NOEXCEPT;\n";
if (Guarded)
OS << "#endif // " << FunctionSpec->getValueAsString("Guard") << "\n";
OS << "\n";
}
// Make another pass over entrypoints to emit object declarations.
for (const auto &Name : EntrypointNameList) {
auto Iter = G.ObjectSpecMap.find(Name);
if (Iter == G.ObjectSpecMap.end())
continue;
const llvm::Record *ObjectSpec = Iter->second;
auto Type = ObjectSpec->getValueAsString("Type");
OS << "extern " << Type << " " << Name << ";\n";
}
OS << "__END_C_DECLS\n";
// Undef file-level attribute macros.
emitUndefsForAttributeMacros(MacroAttr, OS);
}
void writePublicAPI(llvm::raw_ostream &OS, const llvm::RecordKeeper &Records) {}
const char PublicAPICommand::Name[] = "public_api";
void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader,
const llvm::RecordKeeper &Records,
const Command::ErrorReporter &Reporter) const {
if (Args.size() != 0)
Reporter.printFatalError("public_api command does not take any arguments.");
APIIndexer G(StdHeader, Records);
writeAPIFromIndex(G, EntrypointNameList, OS);
}
} // namespace llvm_libc

View File

@ -1,48 +0,0 @@
//===-- Implementation of PublicAPICommand ----------------------*- C++ -*-===//
//
// 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_UTILS_HDRGEN_PUBLICAPICOMMAND_H
#define LLVM_LIBC_UTILS_HDRGEN_PUBLICAPICOMMAND_H
#include "Command.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
namespace llvm {
class raw_ostream;
class Record;
class RecordKeeper;
} // namespace llvm
namespace llvm_libc {
enum class AttributeStyle { Cxx11 = 0, Gnu = 1, Declspec = 2 };
enum class AttributeNamespace { None = 0, Clang = 1, Gnu = 2 };
class PublicAPICommand : public Command {
private:
const std::vector<std::string> &EntrypointNameList;
public:
static const char Name[];
PublicAPICommand(const std::vector<std::string> &EntrypointNames)
: EntrypointNameList(EntrypointNames) {}
void run(llvm::raw_ostream &OS, const ArgVector &Args,
llvm::StringRef StdHeader, const llvm::RecordKeeper &Records,
const Command::ErrorReporter &Reporter) const override;
};
} // namespace llvm_libc
#endif // LLVM_LIBC_UTILS_HDRGEN_PUBLICAPICOMMAND_H

View File

@ -1,5 +0,0 @@
# The LLVM libc header generation system
LLVM libc uses a header generation scheme to generate public as well as internal
header files. This directory contains the implementation of the header generator
which drives this header generation scheme.

View File

@ -1,173 +0,0 @@
//===-- Implementation of APIIndexer class --------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "APIIndexer.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
namespace llvm_libc {
static const char NamedTypeClassName[] = "NamedType";
static const char PtrTypeClassName[] = "PtrType";
static const char RestrictedPtrTypeClassName[] = "RestrictedPtrType";
static const char ConstTypeClassName[] = "ConstType";
static const char StructTypeClassName[] = "Struct";
static const char StandardSpecClassName[] = "StandardSpec";
static const char PublicAPIClassName[] = "PublicAPI";
static bool isa(const llvm::Record *Def, const llvm::Record *TypeClass) {
const llvm::RecordRecTy *RecordType = Def->getType();
llvm::ArrayRef<const llvm::Record *> Classes = RecordType->getClasses();
// We want exact types. That is, we don't want the classes listed in
// spec.td to be subclassed. Hence, we do not want the record |Def|
// to be of more than one class type..
if (Classes.size() != 1)
return false;
return Classes[0] == TypeClass;
}
bool APIIndexer::isaNamedType(const llvm::Record *Def) {
return isa(Def, NamedTypeClass);
}
bool APIIndexer::isaStructType(const llvm::Record *Def) {
return isa(Def, StructClass);
}
bool APIIndexer::isaPtrType(const llvm::Record *Def) {
return isa(Def, PtrTypeClass);
}
bool APIIndexer::isaConstType(const llvm::Record *Def) {
return isa(Def, ConstTypeClass);
}
bool APIIndexer::isaRestrictedPtrType(const llvm::Record *Def) {
return isa(Def, RestrictedPtrTypeClass);
}
bool APIIndexer::isaStandardSpec(const llvm::Record *Def) {
return isa(Def, StandardSpecClass);
}
bool APIIndexer::isaPublicAPI(const llvm::Record *Def) {
return isa(Def, PublicAPIClass);
}
std::string APIIndexer::getTypeAsString(const llvm::Record *TypeRecord) {
if (isaNamedType(TypeRecord) || isaStructType(TypeRecord)) {
return std::string(TypeRecord->getValueAsString("Name"));
} else if (isaPtrType(TypeRecord)) {
return getTypeAsString(TypeRecord->getValueAsDef("PointeeType")) + " *";
} else if (isaConstType(TypeRecord)) {
return std::string("const ") +
getTypeAsString(TypeRecord->getValueAsDef("UnqualifiedType"));
} else if (isaRestrictedPtrType(TypeRecord)) {
return getTypeAsString(TypeRecord->getValueAsDef("PointeeType")) +
" *__restrict";
} else {
llvm::PrintFatalError(TypeRecord->getLoc(), "Invalid type.\n");
}
}
void APIIndexer::indexStandardSpecDef(const llvm::Record *StandardSpec) {
auto HeaderSpecList = StandardSpec->getValueAsListOfDefs("Headers");
for (const llvm::Record *HeaderSpec : HeaderSpecList) {
llvm::StringRef Header = HeaderSpec->getValueAsString("Name");
if (!StdHeader.has_value() || Header == StdHeader) {
PublicHeaders.emplace(Header);
auto MacroSpecList = HeaderSpec->getValueAsListOfDefs("Macros");
// TODO: Trigger a fatal error on duplicate specs.
for (const llvm::Record *MacroSpec : MacroSpecList)
MacroSpecMap[std::string(MacroSpec->getValueAsString("Name"))] =
MacroSpec;
auto TypeSpecList = HeaderSpec->getValueAsListOfDefs("Types");
for (const llvm::Record *TypeSpec : TypeSpecList)
TypeSpecMap[std::string(TypeSpec->getValueAsString("Name"))] = TypeSpec;
auto FunctionSpecList = HeaderSpec->getValueAsListOfDefs("Functions");
for (const llvm::Record *FunctionSpec : FunctionSpecList) {
auto FunctionName = std::string(FunctionSpec->getValueAsString("Name"));
FunctionSpecMap[FunctionName] = FunctionSpec;
FunctionToHeaderMap[FunctionName] = std::string(Header);
}
auto EnumerationSpecList =
HeaderSpec->getValueAsListOfDefs("Enumerations");
for (const llvm::Record *EnumerationSpec : EnumerationSpecList) {
EnumerationSpecMap[std::string(
EnumerationSpec->getValueAsString("Name"))] = EnumerationSpec;
}
auto ObjectSpecList = HeaderSpec->getValueAsListOfDefs("Objects");
for (const llvm::Record *ObjectSpec : ObjectSpecList) {
auto ObjectName = std::string(ObjectSpec->getValueAsString("Name"));
ObjectSpecMap[ObjectName] = ObjectSpec;
ObjectToHeaderMap[ObjectName] = std::string(Header);
}
}
}
}
void APIIndexer::indexPublicAPIDef(const llvm::Record *PublicAPI) {
// While indexing the public API, we do not check if any of the entities
// requested is from an included standard. Such a check is done while
// generating the API.
auto MacroDefList = PublicAPI->getValueAsListOfDefs("Macros");
for (const llvm::Record *MacroDef : MacroDefList)
MacroDefsMap[std::string(MacroDef->getValueAsString("Name"))] = MacroDef;
auto TypeList = PublicAPI->getValueAsListOfStrings("Types");
for (llvm::StringRef TypeName : TypeList)
RequiredTypes.insert(std::string(TypeName));
auto StructList = PublicAPI->getValueAsListOfStrings("Structs");
for (llvm::StringRef StructName : StructList)
Structs.insert(std::string(StructName));
auto FunctionList = PublicAPI->getValueAsListOfStrings("Functions");
for (llvm::StringRef FunctionName : FunctionList)
Functions.insert(std::string(FunctionName));
auto EnumerationList = PublicAPI->getValueAsListOfStrings("Enumerations");
for (llvm::StringRef EnumerationName : EnumerationList)
Enumerations.insert(std::string(EnumerationName));
auto ObjectList = PublicAPI->getValueAsListOfStrings("Objects");
for (llvm::StringRef ObjectName : ObjectList)
Objects.insert(std::string(ObjectName));
}
void APIIndexer::index(const llvm::RecordKeeper &Records) {
NamedTypeClass = Records.getClass(NamedTypeClassName);
PtrTypeClass = Records.getClass(PtrTypeClassName);
RestrictedPtrTypeClass = Records.getClass(RestrictedPtrTypeClassName);
StructClass = Records.getClass(StructTypeClassName);
ConstTypeClass = Records.getClass(ConstTypeClassName);
StandardSpecClass = Records.getClass(StandardSpecClassName);
PublicAPIClass = Records.getClass(PublicAPIClassName);
const auto &DefsMap = Records.getDefs();
for (auto &Pair : DefsMap) {
const llvm::Record *Def = Pair.second.get();
if (isaStandardSpec(Def))
indexStandardSpecDef(Def);
if (isaPublicAPI(Def)) {
if (!StdHeader.has_value() ||
Def->getValueAsString("HeaderName") == StdHeader)
indexPublicAPIDef(Def);
}
}
}
} // namespace llvm_libc

View File

@ -1,86 +0,0 @@
//===-- A class to index libc API listed in tablegen files ------*- C++ -*-===//
//
// 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_UTILS_LIBC_TABLE_GEN_UTILS_API_INDEXER_H
#define LLVM_LIBC_UTILS_LIBC_TABLE_GEN_UTILS_API_INDEXER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/TableGen/Record.h"
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
namespace llvm_libc {
class APIIndexer {
private:
std::optional<llvm::StringRef> StdHeader;
// TableGen classes in spec.td.
const llvm::Record *NamedTypeClass;
const llvm::Record *PtrTypeClass;
const llvm::Record *RestrictedPtrTypeClass;
const llvm::Record *ConstTypeClass;
const llvm::Record *StructClass;
const llvm::Record *StandardSpecClass;
const llvm::Record *PublicAPIClass;
bool isaNamedType(const llvm::Record *Def);
bool isaStructType(const llvm::Record *Def);
bool isaPtrType(const llvm::Record *Def);
bool isaConstType(const llvm::Record *Def);
bool isaRestrictedPtrType(const llvm::Record *Def);
bool isaStandardSpec(const llvm::Record *Def);
bool isaPublicAPI(const llvm::Record *Def);
void indexStandardSpecDef(const llvm::Record *StandardSpec);
void indexPublicAPIDef(const llvm::Record *PublicAPI);
void index(const llvm::RecordKeeper &Records);
public:
using NameToRecordMapping =
std::unordered_map<std::string, const llvm::Record *>;
using NameSet = std::unordered_set<std::string>;
// This indexes all headers, not just a specified one.
explicit APIIndexer(const llvm::RecordKeeper &Records)
: StdHeader(std::nullopt) {
index(Records);
}
APIIndexer(llvm::StringRef Header, const llvm::RecordKeeper &Records)
: StdHeader(Header) {
index(Records);
}
// Mapping from names to records defining them.
NameToRecordMapping MacroSpecMap;
NameToRecordMapping TypeSpecMap;
NameToRecordMapping EnumerationSpecMap;
NameToRecordMapping FunctionSpecMap;
NameToRecordMapping MacroDefsMap;
NameToRecordMapping ObjectSpecMap;
std::unordered_map<std::string, std::string> FunctionToHeaderMap;
std::unordered_map<std::string, std::string> ObjectToHeaderMap;
NameSet RequiredTypes;
NameSet Structs;
NameSet Enumerations;
NameSet Functions;
NameSet Objects;
NameSet PublicHeaders;
std::string getTypeAsString(const llvm::Record *TypeRecord);
};
} // namespace llvm_libc
#endif // LLVM_LIBC_UTILS_LIBC_TABLE_GEN_UTILS_API_INDEXER_H

View File

@ -1,13 +0,0 @@
if (NOT LLVM_LINK_LLVM_DYLIB)
set(flags "DISABLE_LLVM_LINK_LLVM_DYLIB;LINK_COMPONENTS;Support;TableGen")
else()
set(flags "LINK_COMPONENTS;TableGen")
endif()
add_llvm_library(
LibcTableGenUtil
APIIndexer.cpp
APIIndexer.h
${flags}
)
target_include_directories(LibcTableGenUtil PUBLIC ${LIBC_SOURCE_DIR})
target_include_directories(LibcTableGenUtil PRIVATE ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR})

View File

@ -186,13 +186,8 @@ if(LIBC_GPU_BUILD)
list(APPEND RUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES "libc")
endif()
set(NEED_LIBC_HDRGEN FALSE)
if("libc" IN_LIST LLVM_ENABLE_RUNTIMES)
set(NEED_LIBC_HDRGEN TRUE)
endif()
foreach(_name ${LLVM_RUNTIME_TARGETS})
if("libc" IN_LIST RUNTIMES_${_name}_LLVM_ENABLE_RUNTIMES)
set(NEED_LIBC_HDRGEN TRUE)
if("${_name}" STREQUAL "amdgcn-amd-amdhsa" OR "${_name}" STREQUAL "nvptx64-nvidia-cuda")
set(LLVM_LIBC_GPU_BUILD ON)
endif()
@ -202,27 +197,11 @@ if("${LIBC_TARGET_TRIPLE}" STREQUAL "amdgcn-amd-amdhsa" OR
"${LIBC_TARGET_TRIPLE}" STREQUAL "nvptx64-nvidia-cuda")
set(LLVM_LIBC_GPU_BUILD ON)
endif()
if(NEED_LIBC_HDRGEN)
# To build the libc runtime, we need to be able to build few libc build
# tools from the "libc" project. So, we add it to the list of enabled
# projects.
if (NOT "libc" IN_LIST LLVM_ENABLE_PROJECTS)
message(STATUS "Enabling libc project to build libc build tools")
list(APPEND LLVM_ENABLE_PROJECTS "libc")
endif()
if (NOT "libc" IN_LIST LLVM_ENABLE_PROJECTS AND LLVM_LIBC_GPU_BUILD)
message(STATUS "Enabling libc project to build libc testing tools")
list(APPEND LLVM_ENABLE_PROJECTS "libc")
endif()
foreach(proj IN LISTS LLVM_ENABLE_RUNTIMES)
if("${proj}" IN_LIST LLVM_ENABLE_PROJECTS)
# The 'libc' project bootstraps a few executables via the project build and
# should not emit an error currently.
if(NOT (NEED_LIBC_HDRGEN AND "${proj}" STREQUAL "libc"))
message(FATAL_ERROR "Runtime project \"${proj}\" found in LLVM_ENABLE_PROJECTS and LLVM_ENABLE_RUNTIMES. It must only appear in one of them and that one should almost always be LLVM_ENABLE_RUNTIMES.")
endif()
endif()
endforeach()
unset(NEED_LIBC_HDRGEN)
# LLVM_ENABLE_PROJECTS_USED is `ON` if the user has ever used the
# `LLVM_ENABLE_PROJECTS` CMake cache variable. This exists for
# several reasons:

View File

@ -520,24 +520,6 @@ if(build_runtimes)
endif()
endforeach()
endif()
if("libc" IN_LIST LLVM_ENABLE_PROJECTS AND
(LLVM_LIBC_FULL_BUILD OR LLVM_LIBC_GPU_BUILD))
if(LIBC_HDRGEN_EXE)
set(hdrgen_exe ${LIBC_HDRGEN_EXE})
else()
if(TARGET ${LIBC_TABLEGEN_EXE})
set(hdrgen_exe $<TARGET_FILE:${LIBC_TABLEGEN_EXE}>)
else()
set(hdrgen_exe ${LIBC_TABLEGEN_EXE})
endif()
set(hdrgen_deps ${LIBC_TABLEGEN_TARGET})
endif()
if(NOT hdrgen_exe)
message(FATAL_ERROR "libc-hdrgen executable missing")
endif()
list(APPEND extra_cmake_args "-DLIBC_HDRGEN_EXE=${hdrgen_exe}")
list(APPEND extra_deps ${hdrgen_deps})
endif()
if(LLVM_LIBC_GPU_BUILD)
list(APPEND extra_cmake_args "-DLLVM_LIBC_GPU_BUILD=ON")
if("libc" IN_LIST RUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES)