[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:
parent
fdd09e9de5
commit
e0ae7793fc
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
];
|
||||
}
|
@ -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",
|
||||
];
|
||||
}
|
@ -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"];
|
||||
}
|
@ -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 = [];
|
||||
}
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
];
|
||||
}
|
@ -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,
|
||||
];
|
||||
}
|
@ -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,
|
||||
];
|
||||
}
|
@ -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,
|
||||
];
|
||||
}
|
@ -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,
|
||||
];
|
||||
}
|
@ -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,
|
||||
];
|
||||
}
|
1867
libc/spec/posix.td
1867
libc/spec/posix.td
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
1827
libc/spec/stdc.td
1827
libc/spec/stdc.td
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
];
|
||||
}
|
@ -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()
|
||||
|
@ -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)
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
@ -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})
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
@ -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.
|
@ -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
|
@ -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
|
@ -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})
|
@ -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:
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user