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 auto match
= G
.FunctionToHeaderMap
.find(entrypoint
);
30 if (match
== G
.FunctionToHeaderMap
.end()) {
31 auto objectMatch
= G
.ObjectToHeaderMap
.find(entrypoint
);
32 if (objectMatch
!= G
.ObjectToHeaderMap
.end()) {
33 headerFileSet
.insert(objectMatch
->second
);
37 llvm::errs() << "ERROR: entrypoint '" << entrypoint
38 << "' could not be found in spec in any public header\n";
41 headerFileSet
.insert(match
->second
);
43 for (const auto &header
: headerFileSet
)
44 OS
<< "#include <" << header
<< ">\n";
48 OS
<< "extern \"C\" int main() {\n";
49 for (const auto &entrypoint
: EntrypointNamesOption
) {
50 auto match
= G
.FunctionSpecMap
.find(entrypoint
);
51 if (match
== G
.FunctionSpecMap
.end()) {
52 auto objectMatch
= G
.ObjectSpecMap
.find(entrypoint
);
53 if (objectMatch
!= G
.ObjectSpecMap
.end()) {
54 auto entrypointPtr
= entrypoint
+ "_ptr";
55 llvm::Record
*objectSpec
= G
.ObjectSpecMap
[entrypoint
];
56 auto objectType
= objectSpec
->getValueAsString("Type");
57 // We just make sure that the global object is present.
58 OS
<< " " << objectType
<< " *" << entrypointPtr
<< " = &"
59 << entrypoint
<< ";\n";
60 OS
<< " ++" << entrypointPtr
<< ";\n"; // To avoid unused var warning.
63 llvm::errs() << "ERROR: entrypoint '" << entrypoint
64 << "' could not be found in spec in any public header\n";
67 llvm::Record
*functionSpec
= match
->second
;
68 llvm::Record
*retValSpec
= functionSpec
->getValueAsDef("Return");
69 std::string returnType
=
70 G
.getTypeAsString(retValSpec
->getValueAsDef("ReturnType"));
71 // _Noreturn is an indication for the compiler that a function
72 // doesn't return, and isn't a type understood by c++ templates.
73 if (llvm::StringRef(returnType
).contains("_Noreturn"))
76 OS
<< " static_assert(__llvm_libc::cpp::is_same_v<" << returnType
<< '(';
77 auto args
= functionSpec
->getValueAsListOfDefs("Args");
78 for (size_t i
= 0, size
= args
.size(); i
< size
; ++i
) {
79 llvm::Record
*argType
= args
[i
]->getValueAsDef("ArgType");
80 OS
<< G
.getTypeAsString(argType
);
84 OS
<< ") __NOEXCEPT, decltype(" << entrypoint
<< ")>, ";
85 OS
<< '"' << entrypoint
86 << " prototype in TableGen does not match public header" << '"';
94 // We provide dummy malloc and free implementations to support the case
95 // when LLVM libc does to include them.
96 OS
<< "void *malloc(size_t) __NOEXCEPT { return nullptr; }\n";
97 OS
<< "void *realloc(void *, size_t) __NOEXCEPT { return nullptr; }\n";
98 OS
<< "void free(void *) __NOEXCEPT {}\n";
103 int main(int argc
, char *argv
[]) {
104 llvm::cl::ParseCommandLineOptions(argc
, argv
);
105 return TableGenMain(argv
[0], TestGeneratorMain
);