diff --git a/projects/eudsl-tblgen/src/eudsl_tblgen/mlir/__init__.py b/projects/eudsl-tblgen/src/eudsl_tblgen/mlir/__init__.py index c34f2bc1..7d6328ea 100644 --- a/projects/eudsl-tblgen/src/eudsl_tblgen/mlir/__init__.py +++ b/projects/eudsl-tblgen/src/eudsl_tblgen/mlir/__init__.py @@ -18,13 +18,26 @@ def underscore(word: str) -> str: return word.lower() +def camelize(string: str, uppercase_first_letter: bool = True) -> str: + if uppercase_first_letter: + return re.sub(r"(?:^|_)(.)", lambda m: m.group(1).upper(), string) + else: + return string[0].lower() + camelize(string)[1:] + + def map_cpp_to_c_type(t): if t in {"unsigned", "bool", "int8_t", "int16_t", "int32_t", "int64_t"}: return t if t in {"RankedTensorType", "Type"}: return "MlirType" - if t in {"Attribute", "CTALayoutAttr"}: + if t in {"Attribute", "CTALayoutAttr", "StringAttr"}: return "MlirAttribute" + if t in {"StringRef"}: + return "MlirStringRef" + if t in {"Location"}: + return "MlirLocation" + if t in {"TypeID"}: + return "MlirTypeID" warnings.warn(f"unrecognized cpp type {t}") return t @@ -40,12 +53,21 @@ class Param: cpp_type: str param_def: AttrOrTypeParameter + @property + def py_param_name(self): + return underscore(self.param_name) + + @property + def c_param_name(self): + return camelize(self.param_name, False) + + @property def c_param_str(self): - return f"{self.c_type} {self.param_name}" + return f"{self.c_type} {self.c_param_name}" @property def getter_name(self): - return f"mlir{self.class_name}Get{self.param_name}" + return f"mlir{self.class_name}Get{camelize(self.param_name)}" # TODO(max): bad heuristic - should look inside param_def def needs_wrap_unwrap(self): @@ -56,14 +78,21 @@ def needs_wrap_unwrap(self): class ArrayRefParam(Param): c_element_type: str + @property + def c_count_param_name(self): + return f"n{camelize(self.param_name)}" + + @property def c_param_str(self): - return f"{self.c_element_type} *{self.param_name}, unsigned n{self.param_name}s" + return f"{self.c_element_type} *{self.c_param_name}, unsigned {self.c_count_param_name}" def map_params(class_name, params: list[AttrOrTypeParameter]): mapped_params = [] for p in params: cpp_ty = p.get_cpp_type() + if cpp_ty.startswith("::"): + cpp_ty = cpp_ty[2:] p_name = p.get_name() if "ArrayRef" in cpp_ty: element_ty = element_ty_reg.findall(cpp_ty) @@ -100,8 +129,7 @@ def emit_c_attr_or_type_builder( cclass_kind: CClassKind, class_name, params: list[AttrOrTypeParameter] ): mapped_params = map_params(class_name, params) - sig = f"""{cclass_kind} mlir{class_name}{'Attr' if cclass_kind == CClassKind.ATTRIBUTE else 'Type'}Get({', '.join([p.c_param_str() for p in mapped_params])}, MlirContext mlirContext)""" - decl = f"""MLIR_CAPI_EXPORTED {sig};""" + sig = f"""{cclass_kind} mlir{class_name}{'Attr' if cclass_kind == CClassKind.ATTRIBUTE else 'Type'}Get({', '.join([p.c_param_str for p in mapped_params])}, MlirContext mlirContext)""" defn = dedent( f""" {sig} {{ @@ -110,41 +138,42 @@ def emit_c_attr_or_type_builder( ) for p in mapped_params: if isinstance(p, ArrayRefParam): - defn += f" {p.cpp_type} {p.param_name}_ = {{{p.param_name}, n{p.param_name}s}};\n" + defn += f" {p.cpp_type} {p.param_name}_ = {{{p.c_param_name}, {p.c_count_param_name}}};\n" else: - rhs = ( - f"llvm::cast<{p.cpp_type}>(unwrap({p.param_name}))" - if p.needs_wrap_unwrap() - else p.param_name - ) - defn += f" {p.cpp_type} {p.param_name}_ = {rhs};\n" - defn += f" return wrap({class_name}::get(context, {', '.join([p.param_name + '_' for p in mapped_params])}));\n" + if p.needs_wrap_unwrap(): + rhs = f"llvm::cast<{p.cpp_type}>(unwrap({p.c_param_name}))" + defn += f" {p.cpp_type} {p.c_param_name}_ = {rhs};\n" + defn += f" return wrap({class_name}::get(context, {', '.join([(p.c_param_name + '_' if p.needs_wrap_unwrap() else p.c_param_name) for p in mapped_params])}));\n" defn += "}" + decl = dedent( + f"""\ + /// {'Attribute' if cclass_kind == CClassKind.ATTRIBUTE else 'Type'} builder for {class_name} + MLIR_CAPI_EXPORTED {sig}; + """ + ) return decl, defn def emit_c_attr_or_type_field_getter( cclass_kind: CClassKind, class_name, param: AttrOrTypeParameter ): - mapped_param = map_params(class_name, [param])[0] - if isinstance(mapped_param, ArrayRefParam): - sig = f"""void {mapped_param.getter_name}({cclass_kind} mlir{class_name}, {mapped_param.c_element_type}** {mapped_param.param_name}Ptr, unsigned *n{mapped_param.param_name}s)""" - decl = f"MLIR_CAPI_EXPORTED {sig};" + mp = map_params(class_name, [param])[0] + if isinstance(mp, ArrayRefParam): + sig = f"""void {mp.getter_name}({cclass_kind} mlir{class_name}, {mp.c_element_type}** {mp.c_param_name}CPtr, unsigned *{mp.c_count_param_name})""" defn = dedent( f""" {sig} {{ - {mapped_param.param_def.get_cpp_accessor_type()} {mapped_param.param_name} = llvm::cast<{class_name}>(unwrap(mlir{class_name})).{mapped_param.param_def.get_accessor_name()}(); - *n{mapped_param.param_name}s = {mapped_param.param_name}.size(); - *{mapped_param.param_name}Ptr = const_cast<{mapped_param.c_element_type}*>({mapped_param.param_name}.data()); + {mp.cpp_type} {mp.param_name} = llvm::cast<{class_name}>(unwrap(mlir{class_name})).{mp.param_def.get_accessor_name()}(); + *{mp.c_count_param_name} = {mp.param_name}.size(); + *{mp.c_param_name}CPtr = const_cast<{mp.c_element_type}*>({mp.param_name}.data()); }} """ ) else: - sig = f"""{mapped_param.c_type} {mapped_param.getter_name}({cclass_kind} mlir{class_name})""" - decl = f"""MLIR_CAPI_EXPORTED {sig};""" - ret = f"llvm::cast<{class_name}>(unwrap(mlir{class_name})).{mapped_param.param_def.get_accessor_name()}()" - if mapped_param.needs_wrap_unwrap(): + sig = f"""{mp.c_type} {mp.getter_name}({cclass_kind} mlir{class_name})""" + ret = f"llvm::cast<{class_name}>(unwrap(mlir{class_name})).{mp.param_def.get_accessor_name()}()" + if mp.needs_wrap_unwrap(): ret = f"wrap({ret})" defn = dedent( f""" @@ -154,6 +183,12 @@ def emit_c_attr_or_type_field_getter( """ ) + decl = dedent( + f"""\ + /// Getter for {mp.param_name} of {class_name} + MLIR_CAPI_EXPORTED {sig}; + """ + ) return decl, defn @@ -169,7 +204,12 @@ def emit_attr_or_type_nanobind_class( helper_decls = [] helper_defns = [] helper_decls.append( - f"MLIR_CAPI_EXPORTED MlirTypeID mlir{class_name}GetTypeID(void);" + dedent( + f"""\ + /// TypeID Getter for {class_name} + MLIR_CAPI_EXPORTED MlirTypeID mlir{class_name}GetTypeID(void); + """ + ) ) helper_defns.append( dedent( @@ -181,7 +221,11 @@ def emit_attr_or_type_nanobind_class( ) ) helper_decls.append( - f"MLIR_CAPI_EXPORTED bool isaMlir{class_name}({mlir_attr_or_mlir_type} thing);" + dedent( + f"""\ + MLIR_CAPI_EXPORTED bool isaMlir{class_name}({mlir_attr_or_mlir_type} thing); + """ + ) ) helper_defns.append( dedent( @@ -211,10 +255,10 @@ def emit_attr_or_type_nanobind_class( help_str = [] for mp in mapped_params: if isinstance(mp, ArrayRefParam): - arg_str.append(f"{mp.param_name}.data(), {mp.param_name}.size()") + arg_str.append(f"{mp.c_param_name}.data(), {mp.c_param_name}.size()") else: - arg_str.append(f"{mp.param_name}") - help_str.append(f'"{underscore(mp.param_name)}"_a') + arg_str.append(f"{mp.c_param_name}") + help_str.append(f'"{mp.py_param_name}"_a') arg_str.append("context") arg_str = ", ".join(arg_str) @@ -232,18 +276,18 @@ def emit_attr_or_type_nanobind_class( if isinstance(mp, ArrayRefParam): s += dedent( f""" - nb{class_name}.def_property_readonly("{underscore(mp.param_name)}", []({mlir_attr_or_mlir_type} self) {{ - unsigned n{mp.param_name}s; - {mp.c_element_type}* {mp.param_name}Ptr; - {mp.getter_name}(self, &{mp.param_name}Ptr, &n{mp.param_name}s); - return std::vector<{mp.c_element_type}>{{{mp.param_name}Ptr, {mp.param_name}Ptr + n{mp.param_name}s}}; + nb{class_name}.def_property_readonly("{mp.py_param_name}", []({mlir_attr_or_mlir_type} self) {{ + unsigned {mp.c_count_param_name}; + {mp.c_element_type}* {mp.c_param_name}; + {mp.getter_name}(self, &{mp.c_param_name}, &{mp.c_count_param_name}); + return std::vector<{mp.c_element_type}>{{{mp.c_param_name}, {mp.c_param_name} + {mp.c_count_param_name}}}; }}); """ ) else: s += dedent( f""" - nb{class_name}.def_property_readonly("{underscore(mp.param_name)}", []({'MlirAttribute' if cclass_kind == CClassKind.ATTRIBUTE else 'MlirType'} self) {{ + nb{class_name}.def_property_readonly("{mp.py_param_name}", []({'MlirAttribute' if cclass_kind == CClassKind.ATTRIBUTE else 'MlirType'} self) {{ return {mp.getter_name}(self); }}); """ @@ -259,8 +303,6 @@ def emit_decls_defns_nbclasses(cclass_kind: CClassKind, defs): for d in defs: params = list(d.get_parameters()) if params: - base_class_name = d.get_cpp_base_class_name() - assert base_class_name in {"::mlir::Attribute", "::mlir::Type"} class_name = d.get_cpp_class_name() decl, defn = emit_c_attr_or_type_builder(cclass_kind, class_name, params) decls.append(decl) diff --git a/projects/eudsl-tblgen/tests/td/AttrTypeBase.td b/projects/eudsl-tblgen/tests/td/AttrTypeBase.td index faa8d607..7904a0a2 100644 --- a/projects/eudsl-tblgen/tests/td/AttrTypeBase.td +++ b/projects/eudsl-tblgen/tests/td/AttrTypeBase.td @@ -56,6 +56,9 @@ class ParamNativeTypeTrait class GenInternalTypeTrait : GenInternalTrait; class PredTypeTrait : PredTrait; +// Trait required to be added to any type which is mutable. +def MutableType : NativeTypeTrait<"IsMutable">; + //===----------------------------------------------------------------------===// // Builders //===----------------------------------------------------------------------===// diff --git a/projects/eudsl-tblgen/tests/td/BuiltinDialect.td b/projects/eudsl-tblgen/tests/td/BuiltinDialect.td new file mode 100644 index 00000000..461f2c7f --- /dev/null +++ b/projects/eudsl-tblgen/tests/td/BuiltinDialect.td @@ -0,0 +1,40 @@ +//===-- BuiltinDialect.td - Builtin dialect definition -----*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains the definition of the Builtin dialect. This dialect +// contains all of the attributes, operations, and types that are core to MLIR. +// +//===----------------------------------------------------------------------===// + +#ifndef BUILTIN_BASE +#define BUILTIN_BASE + +include "OpBase.td" + +def Builtin_Dialect : Dialect { + let summary = + "A dialect containing the builtin Attributes, Operations, and Types"; + let name = "builtin"; + let cppNamespace = "::mlir"; + let useDefaultAttributePrinterParser = 0; + let useDefaultTypePrinterParser = 0; + let extraClassDeclaration = [{ + private: + // Register the builtin Attributes. + void registerAttributes(); + // Register the builtin Location Attributes. + void registerLocationAttributes(); + // Register the builtin Types. + void registerTypes(); + + public: + }]; + +} + +#endif // BUILTIN_BASE diff --git a/projects/eudsl-tblgen/tests/td/BuiltinLocationAttributes.td b/projects/eudsl-tblgen/tests/td/BuiltinLocationAttributes.td new file mode 100644 index 00000000..e8b9b86e --- /dev/null +++ b/projects/eudsl-tblgen/tests/td/BuiltinLocationAttributes.td @@ -0,0 +1,341 @@ +//===- BuiltinLocationAttributes.td - Builtin Locations ----*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the set of builtin MLIR location attributes. +// +//===----------------------------------------------------------------------===// + +#ifndef BUILTIN_LOCATION_ATTRIBUTES_TD +#define BUILTIN_LOCATION_ATTRIBUTES_TD + +include "AttrTypeBase.td" +include "BuiltinDialect.td" + +// Base class for Builtin dialect location attributes. +class Builtin_LocationAttr traits = []> + : LocationAttrDef { + let cppClassName = name; + let mnemonic = ?; +} + +//===----------------------------------------------------------------------===// +// CallSiteLoc +//===----------------------------------------------------------------------===// + +def CallSiteLoc : Builtin_LocationAttr<"CallSiteLoc"> { + let summary = "A callsite source location"; + let description = [{ + Syntax: + + ``` + callsite-location ::= `callsite` `(` location `at` location `)` + ``` + + An instance of this location allows for representing a directed stack of + location usages. This connects a location of a `callee` with the location + of a `caller`. + + Example: + + ```mlir + loc(callsite("foo" at "mysource.cc":10:8)) + ``` + }]; + let parameters = (ins "Location":$callee, "Location":$caller); + let builders = [ + AttrBuilderWithInferredContext<(ins "Location":$callee, + "Location":$caller), [{ + return $_get(callee->getContext(), callee, caller); + }]>, + AttrBuilderWithInferredContext<(ins "Location":$name, + "ArrayRef":$frames)> + ]; + let skipDefaultBuilders = 1; + let attrName = "builtin.call_site_loc"; +} + +//===----------------------------------------------------------------------===// +// FileLineColRange +//===----------------------------------------------------------------------===// + +def FileLineColRange : Builtin_LocationAttr<"FileLineColRange"> { + let summary = "A file:line:column source location range"; + let description = [{ + Syntax: + + ``` + filelinecol-location ::= string-literal `:` integer-literal `:` + integer-literal + (`to` (integer-literal ?) `:` integer-literal ?) + ``` + + An instance of this location represents a tuple of file, start and end line + number, and start and end column number. It allows for the following + configurations: + + * A single file line location: `file:line`; + * A single file line col location: `file:line:column`; + * A single line range: `file:line:column to :column`; + * A single file range: `file:line:column to line:column`; + + Example: + + ```mlir + loc("mysource.cc":10:8 to 12:18) + ``` + }]; + + let parameters = (ins "StringAttr":$filename, + "unsigned":$start_line, "unsigned":$start_column, + "unsigned":$end_line, "unsigned":$end_column); + let builders = [ + AttrBuilderWithInferredContext<(ins "StringAttr":$filename), [{ + return $_get(filename.getContext(), filename, ArrayRef{}); + }]>, + AttrBuilderWithInferredContext<(ins "StringAttr":$filename, + "unsigned":$line), [{ + return $_get(filename.getContext(), filename, + ArrayRef{line}); + }]>, + AttrBuilderWithInferredContext<(ins "StringAttr":$filename, + "unsigned":$line, + "unsigned":$column), [{ + return $_get(filename.getContext(), filename, + ArrayRef{line, column}); + }]>, + AttrBuilder<(ins "::llvm::StringRef":$filename, + "unsigned":$start_line, + "unsigned":$start_column), [{ + return $_get($_ctxt, + StringAttr::get($_ctxt, filename.empty() ? "-" : filename), + ArrayRef{start_line, start_column}); + }]>, + AttrBuilderWithInferredContext<(ins "::mlir::StringAttr":$filename, + "unsigned":$line, + "unsigned":$start_column, + "unsigned":$end_column), [{ + return $_get(filename.getContext(), filename, + ArrayRef{line, start_column, end_column}); + }]>, + AttrBuilderWithInferredContext<(ins "::mlir::StringAttr":$filename, + "unsigned":$start_line, + "unsigned":$start_column, + "unsigned":$end_line, + "unsigned":$end_column), [{ + return $_get(filename.getContext(), filename, + ArrayRef{start_line, start_column, end_column, end_line}); + }]>, + AttrBuilder<(ins "::llvm::StringRef":$filename, + "unsigned":$start_line, + "unsigned":$start_column, + "unsigned":$end_line, + "unsigned":$end_column), [{ + return $_get($_ctxt, + StringAttr::get($_ctxt, filename.empty() ? "-" : filename), + ArrayRef{start_line, start_column, end_column, end_line}); + }]>, + ]; + + let extraClassDeclaration = [{ + ::mlir::StringAttr getFilename() const; + unsigned getStartLine() const; + unsigned getStartColumn() const; + unsigned getEndColumn() const; + unsigned getEndLine() const; + }]; + let skipDefaultBuilders = 1; + let genAccessors = 0; + let genStorageClass = 0; + let attrName = "builtin.file_line_range"; +} + +//===----------------------------------------------------------------------===// +// FusedLoc +//===----------------------------------------------------------------------===// + +def FusedLoc : Builtin_LocationAttr<"FusedLoc"> { + let summary = "A tuple of other source locations"; + let description = [{ + Syntax: + + ``` + fusion-metadata ::= `<` attribute-value `>` + fused-location ::= `fused` fusion-metadata? `[` (location (`,` location)* )? `]` + ``` + + An instance of a `fused` location represents a grouping of several other + source locations, with optional metadata that describes the context of the + fusion. There are many places within a compiler in which several constructs + may be fused together, e.g. pattern rewriting, that normally result partial + or even total loss of location information. With `fused` locations, this is + a non-issue. + + Example: + + ```mlir + loc(fused["mysource.cc":10:8, "mysource.cc":22:8]) + loc(fused<"CSE">["mysource.cc":10:8, "mysource.cc":22:8]) + ``` + }]; + let parameters = (ins ArrayRefParameter<"Location", "">:$locations, + "Attribute":$metadata); + let extraClassDeclaration = [{ + static Location get(ArrayRef locs, Attribute metadata, + MLIRContext *context); + static Location get(MLIRContext *context, ArrayRef locs) { + return get(locs, Attribute(), context); + } + }]; + let attrName = "builtin.fused_loc"; +} + +//===----------------------------------------------------------------------===// +// NameLoc +//===----------------------------------------------------------------------===// + +def NameLoc : Builtin_LocationAttr<"NameLoc"> { + let summary = "A named source location"; + let description = [{ + Syntax: + + ``` + name-location ::= string-literal (`(` location `)`)? + ``` + + An instance of this location allows for attaching a name to a child location. + This can be useful for representing the locations of variable, or node, + definitions. + + #### Example: + + ```mlir + loc("CSE"("mysource.cc":10:8)) + ``` + }]; + let parameters = (ins "StringAttr":$name, "Location":$childLoc); + let builders = [ + AttrBuilderWithInferredContext<(ins "StringAttr":$name, + "Location":$childLoc), [{ + return $_get(name.getContext(), name, childLoc); + }]>, + AttrBuilderWithInferredContext<(ins "StringAttr":$name), [{ + return $_get(name.getContext(), name, + UnknownLoc::get(name.getContext())); + }]> + ]; + let skipDefaultBuilders = 1; + let attrName = "builtin.name_loc"; +} + +//===----------------------------------------------------------------------===// +// OpaqueLoc +//===----------------------------------------------------------------------===// + +def OpaqueLoc : Builtin_LocationAttr<"OpaqueLoc"> { + let summary = "An opaque source location"; + let description = [{ + An instance of this location essentially contains a pointer to some data + structure that is external to MLIR and an optional location that can be used + if the first one is not suitable. Since it contains an external structure, + only the optional location is used during serialization. + + #### Example: + + ```mlir + %0 = "example.operation"() : () -> i32 loc("mysource") + %1 = arith.constant 4 : index loc(callsite("mysum" at "mysource.cc":10:8)) + ``` + }]; + let parameters = (ins "uintptr_t":$underlyingLocation, + "TypeID":$underlyingTypeID, + "Location":$fallbackLocation); + let builders = [ + AttrBuilderWithInferredContext<(ins "uintptr_t":$underlyingLocation, + "TypeID":$underlyingTypeID, + "Location":$fallbackLocation), [{ + return $_get(fallbackLocation->getContext(), underlyingLocation, + underlyingTypeID, fallbackLocation); + }]> + ]; + let extraClassDeclaration = [{ + /// Returns an instance of opaque location which contains a given pointer to + /// an object. The corresponding MLIR location is set to UnknownLoc. + template + static OpaqueLoc get(T underlyingLocation, MLIRContext *context); + + /// Returns an instance of opaque location which contains a given pointer to + /// an object and an additional MLIR location. + template + static OpaqueLoc get(T underlyingLocation, Location fallbackLocation) { + return get(reinterpret_cast(underlyingLocation), + TypeID::get(), fallbackLocation); + } + + /// Returns a pointer to some data structure that opaque location stores. + template static T getUnderlyingLocation(Location location) { + assert(isa(location)); + return reinterpret_cast( + mlir::cast(static_cast(location)) + .getUnderlyingLocation()); + } + + /// Returns a pointer to some data structure that opaque location stores. + /// Returns nullptr if provided location is not opaque location or if it + /// contains a pointer of different type. + template + static T getUnderlyingLocationOrNull(Location location) { + return isa(location) + ? reinterpret_cast(mlir::cast( + static_cast(location)) + .getUnderlyingLocation()) + : T(nullptr); + } + + /// Checks whether provided location is opaque location and contains a + /// pointer to an object of particular type. + template static bool isa(Location location) { + auto opaque_loc = + mlir::dyn_cast(static_cast(location)); + return opaque_loc && opaque_loc.getUnderlyingTypeID() == TypeID::get(); + } + }]; + let skipDefaultBuilders = 1; + let attrName = "builtin.opaque_loc"; +} + +//===----------------------------------------------------------------------===// +// UnknownLoc +//===----------------------------------------------------------------------===// + +def UnknownLoc : Builtin_LocationAttr<"UnknownLoc"> { + let summary = "An unspecified source location"; + let description = [{ + Syntax: + + ``` + unknown-location ::= `?` + ``` + + Source location information is an extremely integral part of the MLIR + infrastructure. As such, location information is always present in the IR, + and must explicitly be set to unknown. Thus, an instance of the `unknown` + location represents an unspecified source location. + + Example: + + ```mlir + loc(?) + ``` + }]; + let extraClassDeclaration = [{ + static UnknownLoc get(MLIRContext *context); + }]; + let attrName = "builtin.unknown_loc"; +} + +#endif // BUILTIN_LOCATION_ATTRIBUTES_TD diff --git a/projects/eudsl-tblgen/tests/test_c_api_emission.py b/projects/eudsl-tblgen/tests/test_c_api_emission.py index f472a66b..e2ea5366 100644 --- a/projects/eudsl-tblgen/tests/test_c_api_emission.py +++ b/projects/eudsl-tblgen/tests/test_c_api_emission.py @@ -72,3 +72,33 @@ def test_types(record_keeper_triton_gpu_types): for h in hdefn: print(h) print(n) + + +@pytest.fixture(scope="function") +def record_keeper_builtin_attributes(): + here = Path(__file__).parent + return RecordKeeper().parse_td( + str(here / "td" / "BuiltinLocationAttributes.td"), [str(here / "td")] + ) + + +def test_builtin_attributes(record_keeper_builtin_attributes): + all_defs = collect_all_attr_or_type_defs( + collect_all_defs(record_keeper_builtin_attributes) + ) + decls, defns, nbclasses = emit_decls_defns_nbclasses(CClassKind.ATTRIBUTE, all_defs) + + print() + for d in decls: + print(d) + for hdecl, _hdefn, n in nbclasses: + for h in hdecl: + print(h) + + for d in defns: + print(d) + + for _hdecl, hdefn, n in nbclasses: + for h in hdefn: + print(h) + print(n)