diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake --- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake +++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake @@ -88,6 +88,7 @@ OUTPUT ${out_file} COMMAND $ -o ${out_file} --header ${ADD_GEN_HDR_GEN_HDR} --def ${in_file} ${replacement_params} -I ${LIBC_SOURCE_DIR} + --entrypoints ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 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 @@ -87,22 +87,6 @@ } def CTypeAPI : PublicAPI<"ctype.h"> { - let Functions = [ - "isalnum", - "isalpha", - "isblank", - "iscntrl", - "isdigit", - "isgraph", - "islower", - "isprint", - "ispunct", - "isspace", - "isupper", - "isxdigit", - "tolower", - "toupper", - ]; } def MathErrHandlingMacro : MacroDef<"math_errhandling"> { @@ -168,88 +152,9 @@ DoubleT, FloatT, ]; - let Functions = [ - "copysign", - "copysignf", - "copysignl", - "ceil", - "ceilf", - "ceill", - "cosf", - "fabs", - "fabsf", - "fabsl", - "floor", - "floorf", - "floorl", - "fmax", - "fmaxf", - "fmaxl", - "fmin", - "fminf", - "fminl", - "frexp", - "frexpf", - "frexpl", - "hypotf", - "logb", - "logbf", - "logbl", - "modf", - "modff", - "modfl", - "expf", - "exp2f", - "remainderf", - "remainder", - "remainderl", - "remquof", - "remquo", - "remquol", - "round", - "roundf", - "roundl", - "sincosf", - "sinf", - "sqrt", - "sqrtf", - "sqrtl", - "trunc", - "truncf", - "truncl", - ]; } def StringAPI : PublicAPI<"string.h"> { - let Functions = [ - "bzero", - "memchr", - "memcmp", - "memcpy", - "memmove", - "memrchr", - "memset", - "strcat", - "strchr", - "strcmp", - "strcoll", - "strcpy", - "strcspn", - "strerror", - "strlen", - "strncat", - "strncmp", - "strncpy", - "strnlen", - "strpbrk", - "strrchr", - "strspn", - "strstr", - "strtok", - "strtok_r", - "strxfrm", - ]; - let TypeDeclarations = [ SizeT, ]; @@ -264,17 +169,9 @@ SizeT, FILE, ]; - - let Functions = [ - "fwrite", - ]; } def StdlibAPI : PublicAPI<"stdlib.h"> { - let Functions = [ - "_Exit", - "abort", - ]; } def ErrnoAPI : PublicAPI<"errno.h"> { @@ -320,11 +217,6 @@ SizeT, OffT, ]; - - let Functions = [ - "mmap", - "munmap", - ]; } def StructSigactionDefn : TypeDecl<"struct sigaction"> { @@ -352,17 +244,6 @@ StructSigactionDefn, SighandlerTDefn, ]; - - let Functions = [ - "raise", - "sigaction", - "sigdelset", - "sigprocmask", - "sigemptyset", - "sigaddset", - "sigfillset", - "signal", - ]; } def OnceFlag : TypeDecl<"once_flag"> { @@ -412,15 +293,6 @@ "thrd_error", "thrd_nomem", ]; - - let Functions = [ - "call_once", - "mtx_init", - "mtx_lock", - "mtx_unlock", - "thrd_create", - "thrd_join", - ]; } def UniStdAPI : PublicAPI<"unistd.h"> { @@ -428,8 +300,4 @@ SSizeT, SizeT, ]; - - let Functions = [ - "write", - ]; } diff --git a/libc/spec/llvm_libc_ext.td b/libc/spec/llvm_libc_ext.td --- a/libc/spec/llvm_libc_ext.td +++ b/libc/spec/llvm_libc_ext.td @@ -14,7 +14,42 @@ ] >; + HeaderSpec Assert = HeaderSpec< + "assert.h", + [], // Macros + [], // Types + [], // Enumerations + [ + FunctionSpec< + "__assert_fail", + RetValSpec, + [ArgSpec, + ArgSpec, + ArgSpec, + ArgSpec,] + + >, + ] + >; + + HeaderSpec Errno = HeaderSpec< + "errno.h", + [], // Macros + [], // Types + [], // Enumerations + [ + FunctionSpec< + "__errno_location", + RetValSpec, + [ArgSpec] + + >, + ] + >; + let Headers = [ String, + Assert, + Errno, ]; } diff --git a/libc/spec/spec.td b/libc/spec/spec.td --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -48,12 +48,45 @@ def VoidPtr : PtrType; def ConstVoidPtr : ConstType; def SizeTType : NamedType<"size_t">; -def FloatPtr : PtrType; def LongDoublePtr : PtrType; // _Noreturn is really not a type, but it is convenient to treat it as a type. def NoReturn : NamedType<"_Noreturn void">; +//comparison for reference +//def ConstVoidPtr : ConstType; +//ConstType ConstVoidPtr = ConstType; + +//types changed from stdc manually +def VoidRestrictedPtr : RestrictedPtrType; +def ConstVoidRestrictedPtr : ConstType; + +def CharPtr : PtrType; +def ConstCharPtr : ConstType; +def CharRestrictedPtr : RestrictedPtrType; +def ConstCharRestrictedPtr : ConstType; + +def OnceFlagType : NamedType<"once_flag">; +def OnceFlagTypePtr : PtrType; +// 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; +def ThrdStartTType : NamedType<"thrd_start_t">; +def ThrdTType : NamedType<"thrd_t">; +def ThrdTTypePtr : PtrType; + +def IntPtr : PtrType; +def FloatPtr : PtrType; +def DoublePtr : PtrType; + +def SigHandlerT : NamedType<"__sighandler_t">; + +//added because __assert_fail needs it. +def UnsignedType : NamedType<"unsigned">; + + class Macro { string Name = name; } diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -1,30 +1,7 @@ def StdC : StandardSpec<"stdc"> { - ConstType ConstVoidPtr = ConstType; - RestrictedPtrType VoidRestrictedPtr = RestrictedPtrType; - ConstType ConstVoidRestrictedPtr = ConstType; - - PtrType CharPtr = PtrType; - ConstType ConstCharPtr = ConstType; - RestrictedPtrType CharRestrictedPtr = RestrictedPtrType; - ConstType ConstCharRestrictedPtr = ConstType; - - NamedType OnceFlagType = NamedType<"once_flag">; - PtrType OnceFlagTypePtr = PtrType; - // TODO(sivachandra): Remove this non-standard type when a formal - // way to describe callable types is available. - NamedType CallOnceFuncType = NamedType<"__call_once_func_t">; - 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; - PtrType FloatPtr = PtrType; - PtrType DoublePtr = PtrType; - - NamedType SigHandlerT = NamedType<"__sighandler_t">; + //all other types are defined in spec.td, but these ones would collide with + //the definition of FILE in libc/config/public_api.td, so this one gets to be scoped. NamedType FILE = NamedType<"FILE">; PtrType FILEPtr = PtrType; RestrictedPtrType FILERestrictedPtr = RestrictedPtrType; diff --git a/libc/utils/HdrGen/CMakeLists.txt b/libc/utils/HdrGen/CMakeLists.txt --- a/libc/utils/HdrGen/CMakeLists.txt +++ b/libc/utils/HdrGen/CMakeLists.txt @@ -10,6 +10,8 @@ Main.cpp PublicAPICommand.cpp PublicAPICommand.h + EntrypointsLoader.h + EntrypointsLoader.cpp ) target_include_directories(libc-hdrgen PRIVATE ${LIBC_SOURCE_DIR}) diff --git a/libc/utils/HdrGen/Command.h b/libc/utils/HdrGen/Command.h --- a/libc/utils/HdrGen/Command.h +++ b/libc/utils/HdrGen/Command.h @@ -45,7 +45,8 @@ virtual ~Command(); virtual void run(llvm::raw_ostream &OS, const ArgVector &Args, - llvm::StringRef StdHeader, llvm::RecordKeeper &Records, + llvm::StringRef StdHeader, llvm::StringRef EntrypointsFile, + llvm::RecordKeeper &Records, const ErrorReporter &Reporter) const = 0; }; diff --git a/libc/utils/HdrGen/EntrypointsLoader.h b/libc/utils/HdrGen/EntrypointsLoader.h new file mode 100644 --- /dev/null +++ b/libc/utils/HdrGen/EntrypointsLoader.h @@ -0,0 +1,29 @@ +//===-- A class to index functions listed in entrypoints 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_HDRGEN_ENTRYPOINTS_LOADER_H +#define LLVM_LIBC_UTILS_HDRGEN_ENTRYPOINTS_LOADER_H + +#include "llvm/ADT/StringRef.h" + +#include +#include + +namespace llvm_libc { + +class EntrypointsLoader { +private: +public: + using NameSet = std::unordered_set; +}; + +EntrypointsLoader::NameSet +getFunctionsFromEntrypoints(std::string FilePath, llvm::StringRef HeaderName); +} // namespace llvm_libc + +#endif // LLVM_LIBC_UTILS_HDRGEN_ENTRYPOINTS_LOADER_H diff --git a/libc/utils/HdrGen/EntrypointsLoader.cpp b/libc/utils/HdrGen/EntrypointsLoader.cpp new file mode 100644 --- /dev/null +++ b/libc/utils/HdrGen/EntrypointsLoader.cpp @@ -0,0 +1,83 @@ +//===-- Implementation of EntrpointsLoader 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 "EntrypointsLoader.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/TableGen/Error.h" + +#include "llvm/Support/MemoryBuffer.h" + +#include +#include + +namespace llvm_libc { + +EntrypointsLoader::NameSet +getFunctionsFromEntrypoints(std::string FilePath, llvm::StringRef HeaderName) { + llvm::ErrorOr> FileBuf = + llvm::MemoryBuffer::getFile(FilePath); + + if (!FileBuf) + llvm::PrintFatalError( + "File failed to load entrypoints in EntrypointsLoader\n"); + + EntrypointsLoader::NameSet FunctionSet = *(new EntrypointsLoader::NameSet()); + std::string HeaderNameStripped = std::string(HeaderName.split(".").first); + + llvm::SmallVector Lines; + FileBuf.get()->getBuffer().split(Lines, "\n"); + + bool InSet = false; + llvm::StringRef CurLine; + llvm::SmallVector LineChunks; + + for (unsigned i = 0; i < Lines.size(); i += 1) { + CurLine = Lines[i].trim(' ').trim('\t'); + + if (CurLine.contains("#")) { + CurLine = CurLine.split("#").first; + } + + if (CurLine.size() == 0) { + continue; + } + + if (!InSet && CurLine.startswith("set(")) { + InSet = true; + } else { + if (CurLine.contains(")")) { + InSet = false; + continue; + } else if (CurLine.consume_front("libc.src.")) { + std::string FuncName = std::string(CurLine.rsplit(".").second); + // this should take a line like "libc.src.ctype.isalnum" + // and return just "isalnum" + llvm::StringRef FuncHeaderName = CurLine.rsplit(".").first; + // and this should take the same line and return just "ctype" + + while (FuncHeaderName.contains(".")) { + // this is because libc.src.sys.mman.mmap is in sys/mman + FuncHeaderName = + llvm::StringRef((FuncHeaderName.split(".").first + "/" + + FuncHeaderName.split(".").second) + .str()); + } + + if (FuncName.size() > 0 && + FuncHeaderName.compare(HeaderNameStripped) == 0) { + FunctionSet.insert(FuncName); + } + } + } + } + return FunctionSet; +} + +} // namespace llvm_libc diff --git a/libc/utils/HdrGen/Generator.h b/libc/utils/HdrGen/Generator.h --- a/libc/utils/HdrGen/Generator.h +++ b/libc/utils/HdrGen/Generator.h @@ -31,6 +31,7 @@ class Generator { llvm::StringRef HeaderDefFile; + llvm::StringRef EntrypointsFile; llvm::StringRef StdHeader; std::unordered_map &ArgMap; @@ -44,9 +45,11 @@ void printError(llvm::StringRef Msg); public: - Generator(const std::string &DefFile, const std::string &Header, + Generator(const std::string &DefFile, const std::string &Entrypoints, + const std::string &Header, std::unordered_map &Map) - : HeaderDefFile(DefFile), StdHeader(Header), ArgMap(Map) {} + : HeaderDefFile(DefFile), EntrypointsFile(Entrypoints), StdHeader(Header), + ArgMap(Map) {} void generate(llvm::raw_ostream &OS, llvm::RecordKeeper &Records); }; diff --git a/libc/utils/HdrGen/Generator.cpp b/libc/utils/HdrGen/Generator.cpp --- a/libc/utils/HdrGen/Generator.cpp +++ b/libc/utils/HdrGen/Generator.cpp @@ -105,7 +105,7 @@ Command::ErrorReporter Reporter( llvm::SMLoc::getFromPointer(CommandName.data()), SrcMgr); - Cmd->run(OS, Args, StdHeader, Records, Reporter); + Cmd->run(OS, Args, StdHeader, EntrypointsFile, Records, Reporter); } else if (!Line.startswith(CommentPrefix)) { // There is no comment or command on this line so we just write it as is. OS << P.first << "\n"; diff --git a/libc/utils/HdrGen/IncludeFileCommand.h b/libc/utils/HdrGen/IncludeFileCommand.h --- a/libc/utils/HdrGen/IncludeFileCommand.h +++ b/libc/utils/HdrGen/IncludeFileCommand.h @@ -23,7 +23,8 @@ static const char Name[]; void run(llvm::raw_ostream &OS, const ArgVector &Args, - llvm::StringRef StdHeader, llvm::RecordKeeper &Records, + llvm::StringRef StdHeader, llvm::StringRef EntrypointsFile, + llvm::RecordKeeper &Records, const Command::ErrorReporter &Reporter) const override; }; diff --git a/libc/utils/HdrGen/IncludeFileCommand.cpp b/libc/utils/HdrGen/IncludeFileCommand.cpp --- a/libc/utils/HdrGen/IncludeFileCommand.cpp +++ b/libc/utils/HdrGen/IncludeFileCommand.cpp @@ -19,6 +19,7 @@ void IncludeFileCommand::run(llvm::raw_ostream &OS, const ArgVector &Args, llvm::StringRef StdHeader, + llvm::StringRef EntryPointsFile, llvm::RecordKeeper &Records, const Command::ErrorReporter &Reporter) const { if (Args.size() != 1) { diff --git a/libc/utils/HdrGen/Main.cpp b/libc/utils/HdrGen/Main.cpp --- a/libc/utils/HdrGen/Main.cpp +++ b/libc/utils/HdrGen/Main.cpp @@ -20,6 +20,10 @@ llvm::cl::opt HeaderDefFile("def", llvm::cl::desc("Path to the .h.def file."), llvm::cl::value_desc(""), llvm::cl::Required); +llvm::cl::opt EntrypointsFile( + "entrypoints", + llvm::cl::desc("Path to the entrypoints.txt file for your system."), + llvm::cl::value_desc(""), llvm::cl::Required); llvm::cl::opt StandardHeader( "header", llvm::cl::desc("The standard header file which is to be generated."), @@ -42,7 +46,7 @@ bool HeaderGeneratorMain(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) { std::unordered_map ArgMap; ParseArgValuePairs(ArgMap); - Generator G(HeaderDefFile, StandardHeader, ArgMap); + Generator G(HeaderDefFile, EntrypointsFile, StandardHeader, ArgMap); G.generate(OS, Records); return false; diff --git a/libc/utils/HdrGen/PublicAPICommand.h b/libc/utils/HdrGen/PublicAPICommand.h --- a/libc/utils/HdrGen/PublicAPICommand.h +++ b/libc/utils/HdrGen/PublicAPICommand.h @@ -30,7 +30,8 @@ static const char Name[]; void run(llvm::raw_ostream &OS, const ArgVector &Args, - llvm::StringRef StdHeader, llvm::RecordKeeper &Records, + llvm::StringRef StdHeader, llvm::StringRef EntrypointsFile, + llvm::RecordKeeper &Records, const Command::ErrorReporter &Reporter) const override; }; 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 @@ -8,6 +8,8 @@ #include "PublicAPICommand.h" +#include "EntrypointsLoader.h" + #include "utils/LibcTableGenUtil/APIIndexer.h" #include "llvm/ADT/StringExtras.h" @@ -40,7 +42,8 @@ namespace llvm_libc { -void writeAPIFromIndex(APIIndexer &G, llvm::raw_ostream &OS) { +void writeAPIFromIndex(APIIndexer &G, llvm::StringRef StdHeader, + llvm::StringRef EntrypointsFile, llvm::raw_ostream &OS) { for (auto &Pair : G.MacroDefsMap) { const std::string &Name = Pair.first; if (G.MacroSpecMap.find(Name) == G.MacroSpecMap.end()) @@ -82,8 +85,10 @@ if (G.Enumerations.size() != 0) OS << "};\n\n"; + auto Functions = + getFunctionsFromEntrypoints(std::string(EntrypointsFile), StdHeader); OS << "__BEGIN_C_DECLS\n\n"; - for (auto &Name : G.Functions) { + for (auto &Name : Functions) { if (G.FunctionSpecMap.find(Name) == G.FunctionSpecMap.end()) llvm::PrintFatalError(Name + " not found in any standard spec.\n"); @@ -112,6 +117,7 @@ void PublicAPICommand::run(llvm::raw_ostream &OS, const ArgVector &Args, llvm::StringRef StdHeader, + llvm::StringRef EntrypointsFile, llvm::RecordKeeper &Records, const Command::ErrorReporter &Reporter) const { if (Args.size() != 0) { @@ -119,7 +125,7 @@ } APIIndexer G(StdHeader, Records); - writeAPIFromIndex(G, OS); + writeAPIFromIndex(G, StdHeader, EntrypointsFile, OS); } } // namespace llvm_libc