[flang] Accept polymorphic component element in storage_size
[llvm-project.git] / libc / utils / HdrGen / PrototypeTestGen / PrototypeTestGen.cpp
blob016826faf77ee931ad30428fa987c111aa838258
1 //===-- PrototypeTestGen.cpp ----------------------------------------------===//
2 //
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
6 //
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"
16 namespace {
18 llvm::cl::list<std::string>
19 EntrypointNamesOption("e", llvm::cl::desc("<list of entrypoints>"),
20 llvm::cl::OneOrMore);
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);
34 continue;
37 llvm::errs() << "ERROR: entrypoint '" << entrypoint
38 << "' could not be found in spec in any public header\n";
39 return true;
41 headerFileSet.insert(match->second);
43 for (const auto &header : headerFileSet)
44 OS << "#include <" << header << ">\n";
46 OS << '\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.
61 continue;
63 llvm::errs() << "ERROR: entrypoint '" << entrypoint
64 << "' could not be found in spec in any public header\n";
65 return true;
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"))
74 returnType = "void";
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);
81 if (i < size - 1)
82 OS << ", ";
84 OS << ") __NOEXCEPT, decltype(" << entrypoint << ")>, ";
85 OS << '"' << entrypoint
86 << " prototype in TableGen does not match public header" << '"';
87 OS << ");\n";
90 OS << '\n';
91 OS << " return 0;\n";
92 OS << "}\n\n";
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";
100 return false;
103 int main(int argc, char *argv[]) {
104 llvm::cl::ParseCommandLineOptions(argc, argv);
105 return TableGenMain(argv[0], TestGeneratorMain);