diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -143,3 +143,16 @@ "raise", ]; } + +def ThreadsAPI : PublicAPI<"threads.h"> { + let Enumerations = [ + "mtx_plain", + "mtx_recursive", + "mtx_timed", + "thrd_timedout", + "thrd_success", + "thrd_busy", + "thrd_error", + "thrd_nomem", + ]; +} diff --git a/libc/config/public_api.td b/libc/config/public_api.td --- a/libc/config/public_api.td +++ b/libc/config/public_api.td @@ -24,6 +24,7 @@ string HeaderName = name; list Macros = []; list TypeDeclarations = []; + list Enumerations = []; list Structs = []; list Functions = []; } diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -36,6 +36,14 @@ ) add_gen_header( + threads_h + DEF_FILE threads.h.def + GEN_HDR threads.h + DEPENDS + llvm_libc_common_h +) + +add_gen_header( errno_h DEF_FILE errno.h.def PARAMS diff --git a/libc/include/threads.h.def b/libc/include/threads.h.def new file mode 100644 --- /dev/null +++ b/libc/include/threads.h.def @@ -0,0 +1,16 @@ +//===---------------- C standard library header threads.h -----------------===// +// +// 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_THREADS_H +#define LLVM_LIBC_THREADS_H + +#include <__llvm-libc-common.h> + +%%public_api() + +#endif // LLVM_LIBC_THREADS_H diff --git a/libc/spec/linux.td b/libc/spec/linux.td --- a/libc/spec/linux.td +++ b/libc/spec/linux.td @@ -55,16 +55,12 @@ Macro<"EL2NSYNC">, Macro<"EADV">, Macro<"ECOMM">, - ], - [], // Types - [] // Functions + ] >; HeaderSpec SysMMan = HeaderSpec< "sys/mman.h", - [Macro<"MAP_ANONYMOUS">], - [], // Types - [] // Functions + [Macro<"MAP_ANONYMOUS">] >; HeaderSpec Signal = HeaderSpec< @@ -106,9 +102,7 @@ Macro<"SIGPWR">, Macro<"SIGSYS">, Macro<"SIGUNUSED">, - ], - [], // Types - [] // Functions + ] >; let Headers = [ diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -84,6 +84,7 @@ Macro<"EXDEV">, ], [], // Types + [], // Enumerations [] // Functions >; @@ -107,6 +108,7 @@ SizeTType, OffTType, ], + [], // Enumerations [ FunctionSpec< "mmap", diff --git a/libc/spec/spec.td b/libc/spec/spec.td --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -14,6 +14,15 @@ list Fields; } +class EnumNameValue { + string Name = name; + string Value = value; +} + +class Enum enumerations> : NamedType { + list Enumerations = enumerations; +} + class PtrType : Type { Type PointeeType = type; } @@ -43,6 +52,11 @@ string Name = name; } +class EnumeratedNameValue { + string Name = name; + string Value = value; +} + class Annotation {} class RetValSpec annotations = []> { @@ -63,13 +77,15 @@ } class HeaderSpec macros, - list types, - list functions> { + list macros = [], + list types = [], + list enumerations = [], + list functions = []> { string Name = name; list Functions = functions; list Types = types; list Macros = macros; + list Enumerations = enumerations; } class StandardSpec { diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -8,6 +8,14 @@ RestrictedPtrType CharRestrictedPtr = RestrictedPtrType; ConstType ConstCharRestrictedPtr = ConstType; + NamedType MtxTType = NamedType<"mtx_t">; + PtrType MtxTTypePtr = PtrType; + NamedType ThrdStartTType = NamedType<"thrd_start_t">; + NamedType ThrdTType = NamedType<"thrd_t">; + PtrType ThrdTTypePtr = PtrType; + + PtrType IntPtr = PtrType; + HeaderSpec String = HeaderSpec< "string.h", [ @@ -16,6 +24,7 @@ [ SizeTType, ], + [], // Enumerations [ FunctionSpec< "memcpy", @@ -143,6 +152,7 @@ NamedType<"float_t">, NamedType<"double_t">, ], + [], // Enumerations [ FunctionSpec<"acos", RetValSpec, [ArgSpec]>, FunctionSpec<"acosl", RetValSpec, [ArgSpec]>, @@ -155,6 +165,7 @@ [ // Types SizeTType, ], + [], // Enumerations [ FunctionSpec< "snprintf", @@ -174,9 +185,7 @@ Macro<"EDOM">, Macro<"EILSEQ">, Macro<"ERANGE">, - ], - [], // Types - [] // Functions + ] >; HeaderSpec Signal = HeaderSpec< @@ -197,16 +206,79 @@ NamedType<"sigset_t">, SizeTType, ], + [], // Enumerations [ FunctionSpec<"raise", RetValSpec, [ArgSpec]>, ] >; + HeaderSpec Threads = HeaderSpec< + "threads.h", + [], // Macros + [ + MtxTType, + ThrdStartTType, + ThrdTType, + ], + [ + EnumeratedNameValue<"mtx_plain">, + EnumeratedNameValue<"mtx_recursive">, + EnumeratedNameValue<"mtx_timed">, + EnumeratedNameValue<"thrd_timedout">, + EnumeratedNameValue<"thrd_success">, + EnumeratedNameValue<"thrd_busy">, + EnumeratedNameValue<"thrd_error">, + EnumeratedNameValue<"thrd_nomem">, + ], + [ + FunctionSpec< + "mtx_init", + RetValSpec, + [ + ArgSpec, + ArgSpec, + ] + >, + FunctionSpec< + "mtx_lock", + RetValSpec, + [ + ArgSpec, + ] + >, + FunctionSpec< + "mtx_unlock", + RetValSpec, + [ + ArgSpec, + ] + >, + FunctionSpec< + "thrd_create", + RetValSpec, + [ + ArgSpec, + ArgSpec, + ArgSpec, + ] + >, + FunctionSpec< + "thrd_join", + RetValSpec, + [ + ArgSpec, + ArgSpec, + ] + > + ] + >; + let Headers = [ Errno, Math, String, StdIO, Signal, + Threads, ]; } diff --git a/libc/utils/HdrGen/PublicAPICommand.cpp b/libc/utils/HdrGen/PublicAPICommand.cpp --- a/libc/utils/HdrGen/PublicAPICommand.cpp +++ b/libc/utils/HdrGen/PublicAPICommand.cpp @@ -75,11 +75,13 @@ // Mapping from names to records defining them. NameToRecordMapping MacroSpecMap; NameToRecordMapping TypeSpecMap; + NameToRecordMapping EnumerationSpecMap; NameToRecordMapping FunctionSpecMap; NameToRecordMapping MacroDefsMap; NameToRecordMapping TypeDeclsMap; NameSet Structs; + NameSet Enumerations; NameSet Functions; bool isaNamedType(llvm::Record *Def) { return isa(Def, NamedTypeClass); } @@ -136,6 +138,13 @@ FunctionSpecMap[std::string(FunctionSpec->getValueAsString("Name"))] = FunctionSpec; } + + auto EnumerationSpecList = + HeaderSpec->getValueAsListOfDefs("Enumerations"); + for (llvm::Record *EnumerationSpec : EnumerationSpecList) { + EnumerationSpecMap[std::string( + EnumerationSpec->getValueAsString("Name"))] = EnumerationSpec; + } } } } @@ -159,6 +168,10 @@ 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)); } void index(llvm::RecordKeeper &Records) { @@ -211,6 +224,25 @@ OS << '\n'; } + if (Enumerations.size() != 0) + OS << "enum {" << '\n'; + for (const auto &Name : Enumerations) { + if (EnumerationSpecMap.find(Name) == EnumerationSpecMap.end()) + llvm::PrintFatalError( + Name + " is not listed as an enumeration in any standard spec.\n"); + + llvm::Record *EnumerationSpec = EnumerationSpecMap[Name]; + OS << " " << EnumerationSpec->getValueAsString("Name"); + auto Value = EnumerationSpec->getValueAsString("Value"); + if (Value == "__default__") { + OS << ",\n"; + } else { + OS << " = " << Value << ",\n"; + } + } + if (Enumerations.size() != 0) + OS << "};\n\n"; + OS << "__BEGIN_C_DECLS\n\n"; for (auto &Name : Functions) { if (FunctionSpecMap.find(Name) == FunctionSpecMap.end())