diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index b5b47ae274601..8c1d5e1c3e8ec 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3347,10 +3347,12 @@ def VFork : LibBuiltin<"unistd.h"> { } // POSIX pthread.h -// FIXME: This should be a GNULibBuiltin, but it's currently missing the prototype. -def PthreadCreate : CustomEntry { - let Entry = "LIBBUILTIN(pthread_create, \"\", \"fC<2,3>\", PTHREAD_H, ALL_GNU_LANGUAGES)"; +def PthreadCreate : GNULibBuiltin<"pthread.h"> { + let Spellings = ["pthread_create"]; + let Attributes = [FunctionWithoutBuiltinPrefix, Callback<[2, 3]>]; + // Note that we don't have an expressable prototype so we leave it empty. + let Prototype = ""; } def SigSetJmp : LibBuiltin<"setjmp.h"> { diff --git a/clang/include/clang/Basic/BuiltinsBase.td b/clang/include/clang/Basic/BuiltinsBase.td index cff182f3f282c..8a3f024c20f44 100644 --- a/clang/include/clang/Basic/BuiltinsBase.td +++ b/clang/include/clang/Basic/BuiltinsBase.td @@ -17,6 +17,11 @@ class IndexedAttribute : Attribute { int Index = I; } +class MultiIndexAttribute Is> + : Attribute { + list Indices = Is; +} + // Standard Attributes // ------------------- def NoReturn : Attribute<"r">; @@ -77,6 +82,10 @@ def Constexpr : Attribute<"E">; // Builtin is immediate and must be constant evaluated. Implies Constexpr, and will only be supported in C++20 mode. def Consteval : Attribute<"EG">; +// Callback behavior: the first index argument is called with the arguments +// indicated by the remaining indices. +class Callback ArgIndices> : MultiIndexAttribute<"C", ArgIndices>; + // Builtin kinds // ============= @@ -90,10 +99,6 @@ class Builtin { bit RequiresUndef = 0; } -class CustomEntry { - string Entry; -} - class AtomicBuiltin : Builtin; class TargetBuiltin : Builtin { string Features = ""; diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp index 6c3604adc92b9..f675dd154a7c9 100644 --- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp +++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "TableGenBackends.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -37,6 +38,14 @@ class PrototypeParser { private: void ParsePrototype(StringRef Prototype) { Prototype = Prototype.trim(); + + // Some builtins don't have an expressible prototype, simply emit an empty + // string for them. + if (Prototype.empty()) { + Type = ""; + return; + } + ParseTypes(Prototype); } @@ -236,8 +245,15 @@ void PrintAttributes(const Record *Builtin, BuiltinType BT, raw_ostream &OS) { for (const auto *Attr : Builtin->getValueAsListOfDefs("Attributes")) { OS << Attr->getValueAsString("Mangling"); - if (Attr->isSubClassOf("IndexedAttribute")) + if (Attr->isSubClassOf("IndexedAttribute")) { OS << ':' << Attr->getValueAsInt("Index") << ':'; + } else if (Attr->isSubClassOf("MultiIndexAttribute")) { + OS << '<'; + llvm::ListSeparator Sep(","); + for (int64_t Index : Attr->getValueAsListOfInts("Indices")) + OS << Sep << Index; + OS << '>'; + } } OS << '\"'; } @@ -380,10 +396,6 @@ void clang::EmitClangBuiltins(const RecordKeeper &Records, raw_ostream &OS) { EmitBuiltin(OS, Builtin); } - for (const auto *Entry : Records.getAllDerivedDefinitions("CustomEntry")) { - OS << Entry->getValueAsString("Entry") << '\n'; - } - OS << R"c++( #undef ATOMIC_BUILTIN #undef BUILTIN