1 //===-- PrototypeTestGen.cpp ----------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "utils/LibcTableGenUtil/APIIndexer.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/CommandLine.h"
13 #include "llvm/TableGen/Main.h"
14 #include "llvm/TableGen/Record.h"
18 llvm::cl::list
<std::string
>
19 EntrypointNamesOption("e", llvm::cl::desc("<list of entrypoints>"),
22 } // anonymous namespace
24 bool TestGeneratorMain(llvm::raw_ostream
&OS
, llvm::RecordKeeper
&records
) {
25 OS
<< "#include \"src/__support/CPP/type_traits.h\"\n";
26 llvm_libc::APIIndexer
G(records
);
27 std::unordered_set
<std::string
> headerFileSet
;
28 for (const auto &entrypoint
: EntrypointNamesOption
) {
29 if (entrypoint
== "errno")
31 auto match
= G
.FunctionToHeaderMap
.find(entrypoint
);
32 if (match
== G
.FunctionToHeaderMap
.end()) {
33 auto objectMatch
= G
.ObjectToHeaderMap
.find(entrypoint
);
34 if (objectMatch
!= G
.ObjectToHeaderMap
.end()) {
35 headerFileSet
.insert(objectMatch
->second
);
39 llvm::errs() << "ERROR: entrypoint '" << entrypoint
40 << "' could not be found in spec in any public header\n";
43 headerFileSet
.insert(match
->second
);
45 for (const auto &header
: headerFileSet
)
46 OS
<< "#include <" << header
<< ">\n";
50 OS
<< "extern \"C\" int main() {\n";
51 for (const auto &entrypoint
: EntrypointNamesOption
) {
52 if (entrypoint
== "errno")
54 auto match
= G
.FunctionSpecMap
.find(entrypoint
);
55 if (match
== G
.FunctionSpecMap
.end()) {
56 auto objectMatch
= G
.ObjectSpecMap
.find(entrypoint
);
57 if (objectMatch
!= G
.ObjectSpecMap
.end()) {
58 auto entrypointPtr
= entrypoint
+ "_ptr";
59 llvm::Record
*objectSpec
= G
.ObjectSpecMap
[entrypoint
];
60 auto objectType
= objectSpec
->getValueAsString("Type");
61 // We just make sure that the global object is present.
62 OS
<< " " << objectType
<< " *" << entrypointPtr
<< " = &"
63 << entrypoint
<< ";\n";
64 OS
<< " ++" << entrypointPtr
<< ";\n"; // To avoid unused var warning.
67 llvm::errs() << "ERROR: entrypoint '" << entrypoint
68 << "' could not be found in spec in any public header\n";
71 llvm::Record
*functionSpec
= match
->second
;
72 llvm::Record
*retValSpec
= functionSpec
->getValueAsDef("Return");
73 std::string returnType
=
74 G
.getTypeAsString(retValSpec
->getValueAsDef("ReturnType"));
75 // _Noreturn is an indication for the compiler that a function
76 // doesn't return, and isn't a type understood by c++ templates.
77 if (llvm::StringRef(returnType
).contains("_Noreturn"))
80 OS
<< " static_assert(LIBC_NAMESPACE::cpp::is_same_v<" << returnType
82 auto args
= functionSpec
->getValueAsListOfDefs("Args");
83 for (size_t i
= 0, size
= args
.size(); i
< size
; ++i
) {
84 llvm::Record
*argType
= args
[i
]->getValueAsDef("ArgType");
85 OS
<< G
.getTypeAsString(argType
);
89 OS
<< ") __NOEXCEPT, decltype(" << entrypoint
<< ")>, ";
90 OS
<< '"' << entrypoint
91 << " prototype in TableGen does not match public header" << '"';
102 int main(int argc
, char *argv
[]) {
103 llvm::cl::ParseCommandLineOptions(argc
, argv
);
104 return TableGenMain(argv
[0], TestGeneratorMain
);