From 2d8bd166138c32b4cf141a765db3e2d5849507e4 Mon Sep 17 00:00:00 2001 From: Henrich Lauko Date: Mon, 18 Sep 2023 20:14:04 +0200 Subject: [PATCH] [CIR] Make AST attributes accessible via interfaces. (#250) - Introduces `CIR/Interfaces/ASTAttrInterfaces` which model API of clang AST nodes, but allows to plugin custom attribute, making `CIR` dialect AST independent. - Extends hierarchy of `DeclAttr`s to model `Decl` attributes more faithfully. - Notably all `CIRASTAttr`s are now created uniformly using `makeAstDeclAttr` which builds corresponding Attribute based on `clang::Decl`. --- clang/include/clang/CIR/CMakeLists.txt | 7 + .../include/clang/CIR/Dialect/CMakeLists.txt | 6 - clang/include/clang/CIR/Dialect/IR/CIRAttrs.h | 4 + .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 52 ++++- .../include/clang/CIR/Dialect/IR/CIRDialect.h | 2 + clang/include/clang/CIR/Dialect/IR/CIROps.td | 8 +- clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 8 +- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 3 +- .../clang/CIR/Interfaces/ASTAttrInterfaces.h | 45 +++++ .../clang/CIR/Interfaces/ASTAttrInterfaces.td | 191 ++++++++++++++++++ .../clang/CIR/Interfaces/CMakeLists.txt | 15 ++ clang/lib/CIR/CMakeLists.txt | 1 + clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 4 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 16 +- clang/lib/CIR/CodeGen/CMakeLists.txt | 2 + clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 44 +++- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 55 +---- clang/lib/CIR/Dialect/IR/CMakeLists.txt | 1 + .../lib/CIR/Dialect/Transforms/CMakeLists.txt | 4 +- .../CIR/Dialect/Transforms/LifetimeCheck.cpp | 97 ++++----- .../Dialect/Transforms/LoweringPrepare.cpp | 30 +-- clang/lib/CIR/FrontendAction/CMakeLists.txt | 4 + .../lib/CIR/Interfaces/ASTAttrInterfaces.cpp | 15 ++ clang/lib/CIR/Interfaces/CMakeLists.txt | 14 ++ .../CIR/Lowering/DirectToLLVM/CMakeLists.txt | 4 + .../CIR/Lowering/ThroughMLIR/CMakeLists.txt | 4 + clang/lib/FrontendTool/CMakeLists.txt | 1 + clang/test/CIR/CodeGen/bitfields.cpp | 2 +- clang/test/CIR/CodeGen/dtors.cpp | 2 +- clang/test/CIR/CodeGen/static.cpp | 8 +- clang/test/CIR/CodeGen/struct.cpp | 2 +- clang/test/CIR/CodeGen/union.cpp | 12 +- clang/test/CIR/CodeGen/vtable-rtti.cpp | 2 +- clang/test/CIR/IR/global.cir | 2 +- clang/test/CIR/IR/invalid.cir | 4 +- clang/test/CIR/IR/struct.cir | 2 +- clang/test/CIR/Lowering/array.cir | 8 +- clang/test/CIR/Lowering/globals.cir | 8 +- clang/test/CIR/Lowering/struct.cir | 8 +- clang/test/CIR/Lowering/unions.cir | 6 +- clang/test/CIR/Lowering/variadics.cir | 2 +- 41 files changed, 509 insertions(+), 196 deletions(-) create mode 100644 clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h create mode 100644 clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td create mode 100644 clang/include/clang/CIR/Interfaces/CMakeLists.txt create mode 100644 clang/lib/CIR/Interfaces/ASTAttrInterfaces.cpp create mode 100644 clang/lib/CIR/Interfaces/CMakeLists.txt diff --git a/clang/include/clang/CIR/CMakeLists.txt b/clang/include/clang/CIR/CMakeLists.txt index 0ca0f41c5af4..2028af5232c2 100644 --- a/clang/include/clang/CIR/CMakeLists.txt +++ b/clang/include/clang/CIR/CMakeLists.txt @@ -1 +1,8 @@ +set(MLIR_MAIN_SRC_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include ) # --src-root +set(MLIR_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include ) # --includedir +set(MLIR_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/mlir/include) +include_directories(SYSTEM ${MLIR_INCLUDE_DIR}) +include_directories(SYSTEM ${MLIR_TABLEGEN_OUTPUT_DIR}) + add_subdirectory(Dialect) +add_subdirectory(Interfaces) diff --git a/clang/include/clang/CIR/Dialect/CMakeLists.txt b/clang/include/clang/CIR/Dialect/CMakeLists.txt index 383bf5231f57..cd837615e82f 100644 --- a/clang/include/clang/CIR/Dialect/CMakeLists.txt +++ b/clang/include/clang/CIR/Dialect/CMakeLists.txt @@ -1,9 +1,3 @@ -set(MLIR_MAIN_SRC_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include ) # --src-root -set(MLIR_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include ) # --includedir -set(MLIR_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/mlir/include) -include_directories(SYSTEM ${MLIR_INCLUDE_DIR}) -include_directories(SYSTEM ${MLIR_TABLEGEN_OUTPUT_DIR}) - add_custom_target(clang-cir-doc) # This replicates part of the add_mlir_doc cmake function from MLIR that cannot diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h index c11246306763..d72fc13ba60d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h @@ -16,8 +16,12 @@ #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributeInterfaces.h" +#include "llvm/ADT/SmallVector.h" + #include "clang/CIR/Dialect/IR/CIROpsEnums.h" +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" + //===----------------------------------------------------------------------===// // CIR Dialect Attrs //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index f91dea2db856..8f72062c0c04 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -15,8 +15,11 @@ include "mlir/IR/BuiltinAttributeInterfaces.td" include "mlir/IR/EnumAttr.td" + include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Interfaces/ASTAttrInterfaces.td" + //===----------------------------------------------------------------------===// // CIR Attrs //===----------------------------------------------------------------------===// @@ -394,12 +397,55 @@ class ASTDecl traits = []> // Enable verifier. let genVerifyDecl = 1; + + let extraClassDefinition = [{ + ::mlir::Attribute $cppClass::parse(::mlir::AsmParser &parser, + ::mlir::Type type) { + // We cannot really parse anything AST related at this point + // since we have no serialization/JSON story. + return $cppClass::get(parser.getContext(), nullptr); + } + + void $cppClass::print(::mlir::AsmPrinter &printer) const { + // Nothing to print besides the mnemonics. + } + + LogicalResult $cppClass::verify( + ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, + }] # clang_name # [{ decl) { + return success(); + } + }]; } -def ASTFunctionDeclAttr : ASTDecl<"FunctionDecl", "fndecl">; -def ASTVarDeclAttr : ASTDecl<"VarDecl", "vardecl">; -def ASTRecordDeclAttr : ASTDecl<"RecordDecl", "recdecl">; +def ASTDeclAttr : ASTDecl<"Decl", "decl", [ASTDeclInterface]>; + +def ASTFunctionDeclAttr : ASTDecl<"FunctionDecl", "function.decl", + [ASTFunctionDeclInterface]>; + +def ASTCXXMethodDeclAttr : ASTDecl<"CXXMethodDecl", "cxxmethod.decl", + [ASTCXXMethodDeclInterface]>; + +def ASTCXXConstructorDeclAttr : ASTDecl<"CXXConstructorDecl", + "cxxconstructor.decl", [ASTCXXConstructorDeclInterface]>; + +def ASTCXXConversionDeclAttr : ASTDecl<"CXXConversionDecl", + "cxxconversion.decl", [ASTCXXConversionDeclInterface]>; + +def ASTCXXDestructorDeclAttr : ASTDecl<"CXXDestructorDecl", + "cxxdestructor.decl", [ASTCXXDestructorDeclInterface]>; + +def ASTVarDeclAttr : ASTDecl<"VarDecl", "var.decl", + [ASTVarDeclInterface]>; + +def ASTTypeDeclAttr: ASTDecl<"TypeDecl", "type.decl", + [ASTTypeDeclInterface]>; + +def ASTTagDeclAttr : ASTDecl<"TagDecl", "tag.decl", + [ASTTagDeclInterface]>; +def ASTRecordDeclAttr : ASTDecl<"RecordDecl", "record.decl", + [ASTRecordDeclInterface]>; //===----------------------------------------------------------------------===// // ExtraFuncAttr diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h index a5bbcf2ca91c..7756092404af 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h @@ -31,6 +31,8 @@ #include "clang/CIR/Dialect/IR/CIROpsStructs.h.inc" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" + namespace mlir { namespace OpTrait { diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 64c1a15fbc5d..13e560f4ff4c 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td" include "clang/CIR/Dialect/IR/CIRTypes.td" include "clang/CIR/Dialect/IR/CIRAttrs.td" +include "clang/CIR/Interfaces/ASTAttrInterfaces.td" + include "mlir/Interfaces/CallInterfaces.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/LoopLikeInterface.td" @@ -293,7 +295,7 @@ def AllocaOp : CIR_Op<"alloca", [ StrAttr:$name, UnitAttr:$init, ConfinedAttr, [IntMinValue<0>]>:$alignment, - OptionalAttr:$ast + OptionalAttr:$ast ); let results = (outs Res:$initial_value, UnitAttr:$constant, OptionalAttr:$alignment, - OptionalAttr:$ast + OptionalAttr:$ast ); let regions = (region AnyRegion:$ctorRegion, AnyRegion:$dtorRegion); let assemblyFormat = [{ @@ -1590,7 +1592,7 @@ def FuncOp : CIR_Op<"func", [ OptionalAttr:$arg_attrs, OptionalAttr:$res_attrs, OptionalAttr:$aliasee, - OptionalAttr:$ast); + OptionalAttr:$ast); let regions = (region AnyRegion:$body); let skipDefaultBuilders = 1; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h index 87aea83b744e..1286225f04aa 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -17,16 +17,12 @@ #include "mlir/IR/Types.h" #include "mlir/Interfaces/DataLayoutInterfaces.h" +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" + //===----------------------------------------------------------------------===// // CIR Dialect Types //===----------------------------------------------------------------------===// -namespace mlir { -namespace cir { -class ASTRecordDeclAttr; -} // namespace cir -} // namespace mlir - #define GET_TYPEDEF_CLASSES #include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc" diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 88087f8915ad..ea0738d19245 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -14,6 +14,7 @@ #define MLIR_CIR_DIALECT_CIR_TYPES include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Interfaces/ASTAttrInterfaces.td" include "mlir/Interfaces/DataLayoutInterfaces.td" include "mlir/IR/AttrTypeBase.td" @@ -111,7 +112,7 @@ def CIR_StructType : CIR_Type<"Struct", "struct", "bool":$body, "bool":$packed, "mlir::cir::StructType::RecordKind":$kind, - "std::optional<::mlir::cir::ASTRecordDeclAttr>":$ast + "std::optional":$ast ); let hasCustomAssemblyFormat = 1; diff --git a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h new file mode 100644 index 000000000000..e2f1e16eb511 --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.h @@ -0,0 +1,45 @@ +//===- ASTAttrInterfaces.h - CIR AST Interfaces -----------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_INTERFACES_CIR_AST_ATTR_INTERFACES_H_ +#define MLIR_INTERFACES_CIR_AST_ATTR_INTERFACES_H_ + +#include "mlir/IR/Attributes.h" + +#include "clang/AST/Attr.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Mangle.h" + +namespace mlir { +namespace cir { + +mlir::Attribute makeFuncDeclAttr(const clang::Decl *decl, + mlir::MLIRContext *ctx); + +} // namespace cir +} // namespace mlir + +/// Include the generated interface declarations. +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h.inc" + +namespace mlir { +namespace cir { + +template bool hasAttr(ASTDeclInterface decl) { + if constexpr (std::is_same_v) + return decl.hasOwnerAttr(); + if constexpr (std::is_same_v) + return decl.hasPointerAttr(); + if constexpr (std::is_same_v) + return decl.hasInitPriorityAttr(); +} + +} // namespace cir +} // namespace mlir + +#endif // MLIR_INTERFACES_CIR_AST_ATAR_INTERFACES_H_ diff --git a/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td new file mode 100644 index 000000000000..8aca1d9c8e63 --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td @@ -0,0 +1,191 @@ +//===- ASTAttrInterfaces.td - CIR AST Interface Definitions -----*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_CIR_INTERFACES_AST_ATTR_INTERFACES +#define MLIR_CIR_INTERFACES_AST_ATTR_INTERFACES + +include "mlir/IR/OpBase.td" + +let cppNamespace = "::mlir::cir" in { + def ASTDeclInterface : AttrInterface<"ASTDeclInterface"> { + let methods = [ + InterfaceMethod<"", "bool", "hasOwnerAttr", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->template hasAttr(); + }] + >, + InterfaceMethod<"", "bool", "hasPointerAttr", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->template hasAttr(); + }] + >, + InterfaceMethod<"", "bool", "hasInitPriorityAttr", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->template hasAttr(); + }] + > + ]; + } + + def ASTNamedDeclInterface : AttrInterface<"ASTNamedDeclInterface", + [ASTDeclInterface]> { + let methods = [ + InterfaceMethod<"", "clang::DeclarationName", "getDeclName", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->getDeclName(); + }] + >, + InterfaceMethod<"", "llvm::StringRef", "getName", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->getName(); + }] + > + ]; + } + + def ASTValueDeclInterface : AttrInterface<"ASTValueDeclInterface", + [ASTNamedDeclInterface]>; + + def ASTDeclaratorDeclInterface : AttrInterface<"ASTDeclaratorDeclInterface", + [ASTValueDeclInterface]>; + + def ASTVarDeclInterface : AttrInterface<"ASTVarDeclInterface", + [ASTDeclaratorDeclInterface]> { + let methods = [ + InterfaceMethod<"", "void", "mangleDynamicInitializer", (ins "llvm::raw_ostream&":$Out), [{}], + /*defaultImplementation=*/ [{ + std::unique_ptr MangleCtx( + $_attr.getAstDecl()->getASTContext().createMangleContext()); + MangleCtx->mangleDynamicInitializer($_attr.getAstDecl(), Out); + }] + >, + InterfaceMethod<"", "clang::VarDecl::TLSKind", "getTLSKind", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->getTLSKind(); + }] + > + ]; + } + + def ASTFunctionDeclInterface : AttrInterface<"ASTFunctionDeclInterface", + [ASTDeclaratorDeclInterface]> { + let methods = [ + InterfaceMethod<"", "bool", "isOverloadedOperator", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->isOverloadedOperator(); + }] + >, + InterfaceMethod<"", "bool", "isStatic", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->isStatic(); + }] + > + ]; + } + + def ASTCXXMethodDeclInterface : AttrInterface<"ASTCXXMethodDeclInterface", + [ASTFunctionDeclInterface]> { + let methods = [ + InterfaceMethod<"", "bool", "isCopyAssignmentOperator", (ins), [{}], + /*defaultImplementation=*/ [{ + if (auto decl = dyn_cast($_attr.getAstDecl())) + return decl->isCopyAssignmentOperator(); + return false; + }] + >, + InterfaceMethod<"", "bool", "isMoveAssignmentOperator", (ins), [{}], + /*defaultImplementation=*/ [{ + if (auto decl = dyn_cast($_attr.getAstDecl())) + return decl->isMoveAssignmentOperator(); + return false; + }] + >, + InterfaceMethod<"", "bool", "isConst", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->isConst(); + }] + > + ]; + } + + def ASTCXXConstructorDeclInterface : AttrInterface<"ASTCXXConstructorDeclInterface", + [ASTCXXMethodDeclInterface]> { + let methods = [ + InterfaceMethod<"", "bool", "isDefaultConstructor", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->isDefaultConstructor(); + }] + >, + InterfaceMethod<"", "bool", "isCopyConstructor", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->isCopyConstructor(); + }] + > + ]; + } + + def ASTCXXConversionDeclInterface : AttrInterface<"ASTCXXConversionDeclInterface", + [ASTCXXMethodDeclInterface]>; + + def ASTCXXDestructorDeclInterface : AttrInterface<"ASTCXXDestructorDeclInterface", + [ASTCXXMethodDeclInterface]>; + + def ASTTypeDeclInterface : AttrInterface<"ASTTypeDeclInterface", + [ASTNamedDeclInterface]>; + + def ASTTagDeclInterface : AttrInterface<"ASTTagDeclInterface", + [ASTTypeDeclInterface]> { + let methods = [ + InterfaceMethod<"", "clang::TagTypeKind", "getTagKind", (ins), [{}], + /*defaultImplementation=*/ [{ + return $_attr.getAstDecl()->getTagKind(); + }] + > + ]; + } + + def ASTRecordDeclInterface : AttrInterface<"ASTRecordDeclInterface", + [ASTTagDeclInterface]> { + let methods = [ + InterfaceMethod<"", "bool", "isLambda", (ins), [{}], + /*defaultImplementation=*/ [{ + if (auto ast = clang::dyn_cast($_attr.getAstDecl())) + return ast->isLambda(); + return false; + }] + >, + InterfaceMethod<"", "bool", "hasPromiseType", (ins), [{}], + /*defaultImplementation=*/ [{ + if (!clang::isa($_attr.getAstDecl())) + return false; + for (const auto *sub : $_attr.getAstDecl()->decls()) { + if (auto subRec = clang::dyn_cast(sub)) { + if (subRec->getDeclName().isIdentifier() && + subRec->getName() == "promise_type") { + return true; + } + } + } + return false; + }] + > + ]; + } + + def AnyASTFunctionDeclAttr : Attr< + CPred<"::mlir::isa<::mlir::cir::ASTFunctionDeclInterface>($_self)">, + "AST Function attribute"> { + let storageType = "::mlir::Attribute"; + let returnType = "::mlir::Attribute"; + let convertFromStorage = "$_self"; + let constBuilderCall = "$0"; + } + +} // namespace mlir::cir + +#endif // MLIR_CIR_INTERFACES_AST_ATTR_INTERFACES diff --git a/clang/include/clang/CIR/Interfaces/CMakeLists.txt b/clang/include/clang/CIR/Interfaces/CMakeLists.txt new file mode 100644 index 000000000000..6925b69a2c97 --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/CMakeLists.txt @@ -0,0 +1,15 @@ +# This replicates part of the add_mlir_interface cmake function from MLIR that +# cannot be used here. This happens because it expects to be run inside MLIR +# directory which is not the case for CIR (and also FIR, both have similar +# workarounds). + +# Declare a dialect in the include directory +function(add_clang_mlir_attr_interface interface) + set(LLVM_TARGET_DEFINITIONS ${interface}.td) + mlir_tablegen(${interface}.h.inc -gen-attr-interface-decls) + mlir_tablegen(${interface}.cpp.inc -gen-attr-interface-defs) + add_public_tablegen_target(MLIRCIR${interface}IncGen) + add_dependencies(mlir-generic-headers MLIRCIR${interface}IncGen) +endfunction() + +add_clang_mlir_attr_interface(ASTAttrInterfaces) diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt index 41e07837d21d..093420b4fee3 100644 --- a/clang/lib/CIR/CMakeLists.txt +++ b/clang/lib/CIR/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(Dialect) add_subdirectory(CodeGen) add_subdirectory(FrontendAction) add_subdirectory(Lowering) +add_subdirectory(Interfaces) diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 749f32292e25..20afa615de87 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -132,8 +132,8 @@ static Address buildPointerWithAlignment(const Expr *E, if (BaseInfo) *BaseInfo = InnerBaseInfo; - if (isa(CE)) { - assert(!UnimplementedFeature::tbaa()); + if (isa(CE)) { + assert(!UnimplementedFeature::tbaa()); LValueBaseInfo TargetTypeBaseInfo; CharUnits Align = CGF.CGM.getNaturalPointeeTypeAlignment( diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index f715b8f973c7..2c85d8fa1e13 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -194,7 +194,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, CIRGenModule::~CIRGenModule() {} -bool CIRGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor, bool ExcludeDtor) { +bool CIRGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor, + bool ExcludeDtor) { if (!Ty.isConstant(astCtx) && !Ty->isReferenceType()) return false; @@ -711,7 +712,7 @@ CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *D, mlir::Type Ty, return builder.getGlobalViewAttr(builder.getPointerTo(Ty), globalOp); } -mlir::Operation* CIRGenModule::getWeakRefReference(const ValueDecl *VD) { +mlir::Operation *CIRGenModule::getWeakRefReference(const ValueDecl *VD) { const AliasAttr *AA = VD->getAttr(); assert(AA && "No alias?"); @@ -726,8 +727,8 @@ mlir::Operation* CIRGenModule::getWeakRefReference(const ValueDecl *VD) { mlir::Type DeclTy = getTypes().convertTypeForMem(VD->getType()); if (DeclTy.isa()) { auto F = GetOrCreateCIRFunction(AA->getAliasee(), DeclTy, - GlobalDecl(cast(VD)), - /*ForVtable=*/false); + GlobalDecl(cast(VD)), + /*ForVtable=*/false); F.setLinkage(mlir::cir::GlobalLinkageKind::ExternalWeakLinkage); WeakRefReferences.insert(F); return F; @@ -1805,7 +1806,7 @@ CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name, f = builder.create(loc, name, Ty); if (FD) - f.setAstAttr(builder.getAttr(FD)); + f.setAstAttr(makeFuncDeclAttr(FD, builder.getContext())); if (FD && !FD->hasPrototype()) f.setNoProtoAttr(builder.getUnitAttr()); @@ -1847,7 +1848,7 @@ mlir::Location CIRGenModule::getLocForFunction(const clang::FunctionDecl *FD) { } void CIRGenModule::setExtraAttributesForFunc(FuncOp f, - const clang::FunctionDecl *FD) { + const clang::FunctionDecl *FD) { mlir::NamedAttrList attrs; if (!FD) { @@ -1922,8 +1923,7 @@ void CIRGenModule::setExtraAttributesForFunc(FuncOp f, } f.setExtraAttrsAttr(mlir::cir::ExtraFuncAttributesAttr::get( - builder.getContext(), - attrs.getDictionary(builder.getContext()))); + builder.getContext(), attrs.getDictionary(builder.getContext()))); } /// If the specified mangled name is not in the module, diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt index 7c0474aee006..a379ed464316 100644 --- a/clang/lib/CIR/CodeGen/CMakeLists.txt +++ b/clang/lib/CIR/CodeGen/CMakeLists.txt @@ -38,6 +38,7 @@ add_clang_library(clangCIR DEPENDS MLIRCIR MLIRCIROpsIncGen + MLIRCIRASTAttrInterfacesIncGen ${dialect_libs} LINK_LIBS @@ -47,6 +48,7 @@ add_clang_library(clangCIR ${dialect_libs} MLIRCIR MLIRCIRTransforms + MLIRCIRASTAttrInterfaces MLIRAffineToStandard MLIRAnalysis MLIRDLTIDialect diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 81f51a7976d4..8d7b63d787e3 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -30,11 +30,11 @@ // ClangIR holds back AST references when available. #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" -static void printStructMembers(mlir::AsmPrinter &p, - mlir::ArrayAttr members); +static void printStructMembers(mlir::AsmPrinter &p, mlir::ArrayAttr members); static mlir::ParseResult parseStructMembers(::mlir::AsmParser &parser, - mlir::ArrayAttr &members); + mlir::ArrayAttr &members); #define GET_ATTRDEF_CLASSES #include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc" @@ -42,6 +42,40 @@ static mlir::ParseResult parseStructMembers(::mlir::AsmParser &parser, using namespace mlir; using namespace mlir::cir; +//===----------------------------------------------------------------------===// +// CIR AST Attr helpers +//===----------------------------------------------------------------------===// + +namespace mlir { +namespace cir { + +mlir::Attribute makeFuncDeclAttr(const clang::Decl *decl, + mlir::MLIRContext *ctx) { + return llvm::TypeSwitch(decl) + .Case([ctx](const clang::CXXConstructorDecl *ast) { + return ASTCXXConstructorDeclAttr::get(ctx, ast); + }) + .Case([ctx](const clang::CXXConversionDecl *ast) { + return ASTCXXConversionDeclAttr::get(ctx, ast); + }) + .Case([ctx](const clang::CXXDestructorDecl *ast) { + return ASTCXXDestructorDeclAttr::get(ctx, ast); + }) + .Case([ctx](const clang::CXXMethodDecl *ast) { + return ASTCXXMethodDeclAttr::get(ctx, ast); + }) + .Case([ctx](const clang::FunctionDecl *ast) { + return ASTFunctionDeclAttr::get(ctx, ast); + }) + .Default([](auto) { + llvm_unreachable("unexpected Decl kind"); + return mlir::Attribute(); + }); +} + +} // namespace cir +} // namespace mlir + //===----------------------------------------------------------------------===// // General CIR parsing / printing //===----------------------------------------------------------------------===// @@ -65,14 +99,14 @@ void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const { } static void printStructMembers(mlir::AsmPrinter &printer, - mlir::ArrayAttr members) { + mlir::ArrayAttr members) { printer << '{'; llvm::interleaveComma(members, printer); printer << '}'; } static ParseResult parseStructMembers(mlir::AsmParser &parser, - mlir::ArrayAttr &members) { + mlir::ArrayAttr &members) { SmallVector elts; auto delimiter = AsmParser::Delimiter::Braces; diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index d46a643edf3f..48fe9bc43c1b 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -42,6 +42,7 @@ using namespace mlir::cir; #include "clang/CIR/Dialect/IR/CIROpsStructs.cpp.inc" #include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc" +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" //===----------------------------------------------------------------------===// // CIR Dialect @@ -2306,60 +2307,6 @@ void SignedOverflowBehaviorAttr::print(::mlir::AsmPrinter &printer) const { printer << ">"; } -::mlir::Attribute ASTFunctionDeclAttr::parse(::mlir::AsmParser &parser, - ::mlir::Type type) { - // We cannot really parse anything AST related at this point since we have no - // serialization/JSON story. Even if the attr is parsed, it just holds nullptr - // instead of the AST node. - return get(parser.getContext(), nullptr); -} - -void ASTFunctionDeclAttr::print(::mlir::AsmPrinter &printer) const { - // Nothing to print besides the mnemonics. -} - -LogicalResult ASTFunctionDeclAttr::verify( - ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, - const ::clang::FunctionDecl *decl) { - return success(); -} - -::mlir::Attribute ASTVarDeclAttr::parse(::mlir::AsmParser &parser, - ::mlir::Type type) { - // We cannot really parse anything AST related at this point since we have no - // serialization/JSON story. Even if the attr is parsed, it just holds nullptr - // instead of the AST node. - return get(parser.getContext(), nullptr); -} - -void ASTVarDeclAttr::print(::mlir::AsmPrinter &printer) const { - // Nothing to print besides the mnemonics. -} - -LogicalResult ASTVarDeclAttr::verify( - ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, - const ::clang::VarDecl *decl) { - return success(); -} - -::mlir::Attribute ASTRecordDeclAttr::parse(::mlir::AsmParser &parser, - ::mlir::Type type) { - // We cannot really parse anything AST related at this point since we have no - // serialization/JSON story. Even if the attr is parsed, it just holds nullptr - // instead of the AST node. - return get(parser.getContext(), nullptr); -} - -void ASTRecordDeclAttr::print(::mlir::AsmPrinter &printer) const { - // Nothing to print besides the mnemonics. -} - -LogicalResult ASTRecordDeclAttr::verify( - ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, - const ::clang::RecordDecl *decl) { - return success(); -} - LogicalResult TypeInfoAttr::verify( ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, ::mlir::Type type, ::mlir::ArrayAttr typeinfoData) { diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt index edf18e89ca80..a035b1e51c29 100644 --- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_library(MLIRCIR MLIRCIROpsIncGen MLIRCIREnumsGen MLIRSymbolInterfacesIncGen + MLIRCIRASTAttrInterfacesIncGen LINK_LIBS PUBLIC MLIRIR diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt index 880542f6d889..82952f42a2d2 100644 --- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt @@ -13,7 +13,9 @@ add_clang_library(MLIRCIRTransforms MLIRAnalysis MLIRIR - MLIRCIR MLIRPass MLIRTransformUtils + + MLIRCIR + MLIRCIRASTAttrInterfaces ) diff --git a/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp b/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp index 3bbb91b5b3a1..44f271cacd2d 100644 --- a/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp @@ -77,13 +77,13 @@ struct LifetimeCheckPass : public LifetimeCheckBase { void checkLambdaCaptureStore(StoreOp storeOp); void trackCallToCoroutine(CallOp callOp); - void checkCtor(CallOp callOp, const clang::CXXConstructorDecl *ctor); - void checkMoveAssignment(CallOp callOp, const clang::CXXMethodDecl *m); - void checkCopyAssignment(CallOp callOp, const clang::CXXMethodDecl *m); + void checkCtor(CallOp callOp, ASTCXXConstructorDeclInterface ctor); + void checkMoveAssignment(CallOp callOp, ASTCXXMethodDeclInterface m); + void checkCopyAssignment(CallOp callOp, ASTCXXMethodDeclInterface m); void checkNonConstUseOfOwner(mlir::Value ownerAddr, mlir::Location loc); - void checkOperators(CallOp callOp, const clang::CXXMethodDecl *m); + void checkOperators(CallOp callOp, ASTCXXMethodDeclInterface m); void checkOtherMethodsAndFunctions(CallOp callOp, - const clang::CXXMethodDecl *m); + ASTCXXMethodDeclInterface m); void checkForOwnerAndPointerArguments(CallOp callOp, unsigned firstArgIdx); // TODO: merge both methods below and pass down an enum. @@ -105,12 +105,9 @@ struct LifetimeCheckPass : public LifetimeCheckBase { std::optional currFunc; // Common helpers. - bool isCtorInitPointerFromOwner(CallOp callOp, - const clang::CXXConstructorDecl *ctor); - mlir::Value getNonConstUseOfOwner(CallOp callOp, - const clang::CXXMethodDecl *m); - bool isOwnerOrPointerClassMethod(CallOp callOp, - const clang::CXXMethodDecl *m); + bool isCtorInitPointerFromOwner(CallOp callOp); + mlir::Value getNonConstUseOfOwner(CallOp callOp, ASTCXXMethodDeclInterface m); + bool isOwnerOrPointerClassMethod(CallOp callOp, ASTCXXMethodDeclInterface m); // Diagnostic helpers. void emitInvalidHistory(mlir::InFlightDiagnostic &D, mlir::Value histKey, @@ -894,11 +891,7 @@ void LifetimeCheckPass::checkIf(IfOp ifOp) { template bool isStructAndHasAttr(mlir::Type ty) { if (!ty.isa()) return false; - auto sTy = ty.cast(); - auto recordDecl = sTy.getAst()->getAstDecl(); - if (recordDecl->hasAttr()) - return true; - return false; + return hasAttr(*mlir::cast(ty).getAst()); } static bool isOwnerType(mlir::Type ty) { @@ -1479,14 +1472,14 @@ static FuncOp getCalleeFromSymbol(ModuleOp mod, StringRef name) { return dyn_cast(global); } -static const clang::CXXMethodDecl *getMethod(ModuleOp mod, CallOp callOp) { +static const ASTCXXMethodDeclInterface getMethod(ModuleOp mod, CallOp callOp) { if (!callOp.getCallee()) return nullptr; StringRef name = *callOp.getCallee(); auto method = getCalleeFromSymbol(mod, name); if (!method || method.getBuiltin()) return nullptr; - return dyn_cast(method.getAstAttr().getAstDecl()); + return dyn_cast(method.getAstAttr()); } mlir::Value LifetimeCheckPass::getThisParamPointerCategory(CallOp callOp) { @@ -1514,7 +1507,7 @@ mlir::Value LifetimeCheckPass::getThisParamOwnerCategory(CallOp callOp) { } void LifetimeCheckPass::checkMoveAssignment(CallOp callOp, - const clang::CXXMethodDecl *m) { + ASTCXXMethodDeclInterface m) { // MyPointer::operator=(MyPointer&&)(%dst, %src) // or // MyOwner::operator=(MyOwner&&)(%dst, %src) @@ -1547,7 +1540,7 @@ void LifetimeCheckPass::checkMoveAssignment(CallOp callOp, } void LifetimeCheckPass::checkCopyAssignment(CallOp callOp, - const clang::CXXMethodDecl *m) { + ASTCXXMethodDeclInterface m) { // MyIntOwner::operator=(MyIntOwner&)(%dst, %src) auto dst = getThisParamOwnerCategory(callOp); auto src = callOp.getArgOperand(1); @@ -1570,8 +1563,7 @@ void LifetimeCheckPass::checkCopyAssignment(CallOp callOp, // Example: // MyIntPointer::MyIntPointer(MyIntOwner const&)(%5, %4) // -bool LifetimeCheckPass::isCtorInitPointerFromOwner( - CallOp callOp, const clang::CXXConstructorDecl *ctor) { +bool LifetimeCheckPass::isCtorInitPointerFromOwner(CallOp callOp) { if (callOp.getNumArgOperands() < 2) return false; @@ -1586,7 +1578,7 @@ bool LifetimeCheckPass::isCtorInitPointerFromOwner( } void LifetimeCheckPass::checkCtor(CallOp callOp, - const clang::CXXConstructorDecl *ctor) { + ASTCXXConstructorDeclInterface ctor) { // TODO: zero init // 2.4.2 if the initialization is default initialization or zero // initialization, example: @@ -1595,7 +1587,7 @@ void LifetimeCheckPass::checkCtor(CallOp callOp, // string_view p; // // both results in pset(p) == {null} - if (ctor->isDefaultConstructor()) { + if (ctor.isDefaultConstructor()) { // First argument passed is always the alloca for the 'this' ptr. // Currently two possible actions: @@ -1619,11 +1611,11 @@ void LifetimeCheckPass::checkCtor(CallOp callOp, } // User defined copy ctor calls ... - if (ctor->isCopyConstructor()) { + if (ctor.isCopyConstructor()) { llvm_unreachable("NYI"); } - if (isCtorInitPointerFromOwner(callOp, ctor)) { + if (isCtorInitPointerFromOwner(callOp)) { auto addr = getThisParamPointerCategory(callOp); assert(addr && "expected pointer category"); auto owner = callOp.getArgOperand(1); @@ -1634,11 +1626,11 @@ void LifetimeCheckPass::checkCtor(CallOp callOp, } void LifetimeCheckPass::checkOperators(CallOp callOp, - const clang::CXXMethodDecl *m) { + ASTCXXMethodDeclInterface m) { auto addr = getThisParamOwnerCategory(callOp); if (addr) { // const access to the owner is fine. - if (m->isConst()) + if (m.isConst()) return; // TODO: this is a place where we can hook in some idiom recocgnition // so we don't need to use actual source code annotation to make assumptions @@ -1663,8 +1655,8 @@ void LifetimeCheckPass::checkOperators(CallOp callOp, mlir::Value LifetimeCheckPass::getNonConstUseOfOwner(CallOp callOp, - const clang::CXXMethodDecl *m) { - if (m->isConst()) + ASTCXXMethodDeclInterface m) { + if (m.isConst()) return {}; return getThisParamOwnerCategory(callOp); } @@ -1735,7 +1727,7 @@ void LifetimeCheckPass::checkForOwnerAndPointerArguments(CallOp callOp, } void LifetimeCheckPass::checkOtherMethodsAndFunctions( - CallOp callOp, const clang::CXXMethodDecl *m) { + CallOp callOp, ASTCXXMethodDeclInterface m) { unsigned firstArgIdx = 0; // Looks at a method 'this' pointer: @@ -1748,9 +1740,9 @@ void LifetimeCheckPass::checkOtherMethodsAndFunctions( } bool LifetimeCheckPass::isOwnerOrPointerClassMethod( - CallOp callOp, const clang::CXXMethodDecl *m) { + CallOp callOp, ASTCXXMethodDeclInterface m) { // For the sake of analysis, these behave like regular functions - if (!m || m->isStatic()) + if (!m || m.isStatic()) return false; // Check the object for owner/pointer by looking at the 'this' pointer. return getThisParamPointerCategory(callOp) || @@ -1765,9 +1757,8 @@ bool LifetimeCheckPass::isLambdaType(mlir::Type ty) { auto taskTy = ty.dyn_cast(); if (!taskTy) return false; - auto recordDecl = taskTy.getAst()->getAstDecl(); - if (recordDecl->isLambda()) - IsLambdaTyCache[ty] = true; + if (taskTy.getAst()->isLambda()) + IsLambdaTyCache[ty] = true; return IsLambdaTyCache[ty]; } @@ -1777,25 +1768,15 @@ bool LifetimeCheckPass::isTaskType(mlir::Value taskVal) { if (IsTaskTyCache.count(ty)) return IsTaskTyCache[ty]; - IsTaskTyCache[ty] = false; - auto taskTy = taskVal.getType().dyn_cast(); - if (!taskTy) - return false; - auto recordDecl = taskTy.getAst()->getAstDecl(); - auto *spec = dyn_cast(recordDecl); - if (!spec) - return false; - - for (auto *sub : spec->decls()) { - auto *subRec = dyn_cast(sub); - if (subRec && subRec->getDeclName().isIdentifier() && - subRec->getName() == "promise_type") { - IsTaskTyCache[ty] = true; - break; - } - } + bool result = [&] { + auto taskTy = taskVal.getType().dyn_cast(); + if (!taskTy) + return false; + return taskTy.getAst()->hasPromiseType(); + }(); - return IsTaskTyCache[ty]; + IsTaskTyCache[ty] = result; + return result; } void LifetimeCheckPass::trackCallToCoroutine(CallOp callOp) { @@ -1835,13 +1816,13 @@ void LifetimeCheckPass::checkCall(CallOp callOp) { // From this point on only owner and pointer class methods handling, // starting from special methods. - if (auto ctor = dyn_cast(methodDecl)) + if (auto ctor = dyn_cast(methodDecl)) return checkCtor(callOp, ctor); - if (methodDecl->isMoveAssignmentOperator()) + if (methodDecl.isMoveAssignmentOperator()) return checkMoveAssignment(callOp, methodDecl); - if (methodDecl->isCopyAssignmentOperator()) + if (methodDecl.isCopyAssignmentOperator()) return checkCopyAssignment(callOp, methodDecl); - if (methodDecl->isOverloadedOperator()) + if (methodDecl.isOverloadedOperator()) return checkOperators(callOp, methodDecl); // For any other methods... diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 6ed1846bf277..9e0b9ec4a203 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/Module.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/Passes.h" +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -133,13 +134,10 @@ cir::FuncOp LoweringPreparePass::buildRuntimeFunction( } cir::FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { - auto varDecl = op.getAst()->getAstDecl(); SmallString<256> fnName; { - std::unique_ptr MangleCtx( - astCtx->createMangleContext()); llvm::raw_svector_ostream Out(fnName); - MangleCtx->mangleDynamicInitializer(varDecl, Out); + op.getAst()->mangleDynamicInitializer(Out); // Name numbering uint32_t cnt = dynamicInitializerNames[fnName]++; if (cnt) @@ -153,7 +151,7 @@ cir::FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { auto fnType = mlir::cir::FuncType::get({}, voidTy); FuncOp f = buildRuntimeFunction(builder, fnName, op.getLoc(), fnType, - mlir::cir::GlobalLinkageKind::InternalLinkage); + mlir::cir::GlobalLinkageKind::InternalLinkage); // Move over the initialzation code of the ctor region. auto &block = op.getCtorRegion().front(); @@ -161,10 +159,10 @@ cir::FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { entryBB->getOperations().splice(entryBB->begin(), block.getOperations(), block.begin(), std::prev(block.end())); - // Register the destructor call with __cxa_atexit - assert(varDecl->getTLSKind() == clang::VarDecl::TLS_None && " TLS NYI"); + assert(op.getAst() && op.getAst()->getTLSKind() == clang::VarDecl::TLS_None && + " TLS NYI"); // Create a variable that binds the atexit to this shared object. builder.setInsertionPointToStart(&theModule.getBodyRegion().front()); auto Handle = buildRuntimeVariable(builder, "__dso_handle", op.getLoc(), @@ -180,7 +178,7 @@ cir::FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { assert(dtorCall && "Expected a dtor call"); cir::FuncOp dtorFunc = getCalledFunction(dtorCall); assert(dtorFunc && - isa(dtorFunc.getAst()->getAstDecl()) && + mlir::isa(*dtorFunc.getAst()) && "Expected a dtor call"); // Create a runtime helper function: @@ -198,7 +196,8 @@ cir::FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { FuncOp fnAtExit = buildRuntimeFunction(builder, nameAtExit, op.getLoc(), fnAtExitType); - // Replace the dtor call with a call to __cxa_atexit(&dtor, &var, &__dso_handle) + // Replace the dtor call with a call to __cxa_atexit(&dtor, &var, + // &__dso_handle) builder.setInsertionPointAfter(dtorCall); mlir::Value args[3]; auto dtorPtrTy = mlir::cir::PointerType::get(builder.getContext(), @@ -241,7 +240,8 @@ void LoweringPreparePass::lowerGlobalOp(GlobalOp op) { dtorRegion.getBlocks().clear(); // Add a function call to the variable initialization function. - assert(!op.getAst()->getAstDecl()->getAttr() && + assert(!hasAttr( + mlir::cast(*op.getAst())) && "custom initialization priority NYI"); dynamicInitializers.push_back(f); } @@ -254,8 +254,7 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { SmallVector attrs; for (auto &f : dynamicInitializers) { // TODO: handle globals with a user-specified initialzation priority. - auto ctorAttr = - mlir::cir::GlobalCtorAttr::get(&getContext(), f.getName()); + auto ctorAttr = mlir::cir::GlobalCtorAttr::get(&getContext(), f.getName()); attrs.push_back(ctorAttr); } @@ -286,7 +285,7 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { {}, mlir::cir::VoidType::get(builder.getContext())); FuncOp f = buildRuntimeFunction(builder, fnName, theModule.getLoc(), fnType, - mlir::cir::GlobalLinkageKind::ExternalLinkage); + mlir::cir::GlobalLinkageKind::ExternalLinkage); builder.setInsertionPointToStart(f.addEntryBlock()); for (auto &f : dynamicInitializers) { builder.create(f.getLoc(), f); @@ -304,7 +303,7 @@ void LoweringPreparePass::runOnOp(Operation *op) { void LoweringPreparePass::runOnOperation() { assert(astCtx && "Missing ASTContext, please construct with the right ctor"); - auto* op = getOperation(); + auto *op = getOperation(); if (isa<::mlir::ModuleOp>(op)) { theModule = cast<::mlir::ModuleOp>(op); } @@ -326,7 +325,8 @@ std::unique_ptr mlir::createLoweringPreparePass() { return std::make_unique(); } -std::unique_ptr mlir::createLoweringPreparePass(clang::ASTContext *astCtx) { +std::unique_ptr +mlir::createLoweringPreparePass(clang::ASTContext *astCtx) { auto pass = std::make_unique(); pass->setASTContext(astCtx); return std::move(pass); diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt index c223383d24cf..7201db6502e6 100644 --- a/clang/lib/CIR/FrontendAction/CMakeLists.txt +++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt @@ -10,6 +10,10 @@ add_clang_library(clangCIRFrontendAction DEPENDS MLIRCIROpsIncGen + MLIRCIRASTAttrInterfacesIncGen + MLIRBuiltinLocationAttributesIncGen + MLIRBuiltinTypeInterfacesIncGen + MLIRFunctionInterfacesIncGen LINK_LIBS clangAST diff --git a/clang/lib/CIR/Interfaces/ASTAttrInterfaces.cpp b/clang/lib/CIR/Interfaces/ASTAttrInterfaces.cpp new file mode 100644 index 000000000000..a3f525dd65a3 --- /dev/null +++ b/clang/lib/CIR/Interfaces/ASTAttrInterfaces.cpp @@ -0,0 +1,15 @@ +//====- ASTAttrInterfaces.cpp - Interface to AST Attributes ---------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" + +#include "llvm/ADT/SmallVector.h" + +using namespace mlir::cir; + +/// Include the generated type qualifiers interfaces. +#include "clang/CIR/Interfaces/ASTAttrInterfaces.cpp.inc" diff --git a/clang/lib/CIR/Interfaces/CMakeLists.txt b/clang/lib/CIR/Interfaces/CMakeLists.txt new file mode 100644 index 000000000000..3f41389807d7 --- /dev/null +++ b/clang/lib/CIR/Interfaces/CMakeLists.txt @@ -0,0 +1,14 @@ +add_clang_library(MLIRCIRASTAttrInterfaces + ASTAttrInterfaces.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces + + DEPENDS + MLIRCIRASTAttrInterfacesIncGen + + LINK_LIBS + ${dialect_libs} + MLIRIR + MLIRSupport + ) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt index c7f713e85da0..b252af37dace 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt @@ -12,6 +12,10 @@ add_clang_library(clangCIRLoweringDirectToLLVM DEPENDS MLIRCIREnumsGen MLIRCIROpsIncGen + MLIRCIRASTAttrInterfacesIncGen + MLIRBuiltinLocationAttributesIncGen + MLIRBuiltinTypeInterfacesIncGen + MLIRFunctionInterfacesIncGen LINK_LIBS clangAST diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt index 762e10eb5db3..b130d2ea4807 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt @@ -12,6 +12,10 @@ add_clang_library(clangCIRLoweringThroughMLIR DEPENDS MLIRCIROpsIncGen MLIRCIREnumsGen + MLIRCIRASTAttrInterfacesIncGen + MLIRBuiltinLocationAttributesIncGen + MLIRBuiltinTypeInterfacesIncGen + MLIRFunctionInterfacesIncGen LINK_LIBS clangAST diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt index ceb4d3f91b68..6dae1455010c 100644 --- a/clang/lib/FrontendTool/CMakeLists.txt +++ b/clang/lib/FrontendTool/CMakeLists.txt @@ -23,6 +23,7 @@ if(CLANG_ENABLE_CIR) ) list(APPEND deps MLIRBuiltinLocationAttributesIncGen + MLIRBuiltinTypeInterfacesIncGen ) include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include) diff --git a/clang/test/CIR/CodeGen/bitfields.cpp b/clang/test/CIR/CodeGen/bitfields.cpp index c1f801af1e7c..8f21b363c71e 100644 --- a/clang/test/CIR/CodeGen/bitfields.cpp +++ b/clang/test/CIR/CodeGen/bitfields.cpp @@ -14,5 +14,5 @@ void m() { __long l; } -// CHECK: !ty_22anon22 = !cir.struct +// CHECK: !ty_22anon22 = !cir.struct // CHECK: !ty_22__long22 = !cir.struct}> diff --git a/clang/test/CIR/CodeGen/dtors.cpp b/clang/test/CIR/CodeGen/dtors.cpp index 7e59a8ec7fbe..ae0d148d35ef 100644 --- a/clang/test/CIR/CodeGen/dtors.cpp +++ b/clang/test/CIR/CodeGen/dtors.cpp @@ -37,7 +37,7 @@ class B : public A }; // Class A -// CHECK: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.recdecl.ast> +// CHECK: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.record.decl.ast> // Class B // CHECK: ![[ClassB:ty_.*]] = !cir.struct diff --git a/clang/test/CIR/CodeGen/static.cpp b/clang/test/CIR/CodeGen/static.cpp index d0620e77b050..2d6c892f7028 100644 --- a/clang/test/CIR/CodeGen/static.cpp +++ b/clang/test/CIR/CodeGen/static.cpp @@ -26,7 +26,7 @@ static Init __ioinit2(false); // BEFORE-NEXT: } dtor { // BEFORE-NEXT: %0 = cir.get_global @_ZL8__ioinit : cir.ptr // BEFORE-NEXT: cir.call @_ZN4InitD1Ev(%0) : (!cir.ptr) -> () -// BEFORE-NEXT: } {ast = #cir.vardecl.ast} +// BEFORE-NEXT: } {ast = #cir.var.decl.ast} // BEFORE: cir.global "private" internal @_ZL9__ioinit2 = ctor : !ty_22Init22 { // BEFORE-NEXT: %0 = cir.get_global @_ZL9__ioinit2 : cir.ptr // BEFORE-NEXT: %1 = cir.const(#false) : !cir.bool @@ -34,7 +34,7 @@ static Init __ioinit2(false); // BEFORE-NEXT: } dtor { // BEFORE-NEXT: %0 = cir.get_global @_ZL9__ioinit2 : cir.ptr // BEFORE-NEXT: cir.call @_ZN4InitD1Ev(%0) : (!cir.ptr) -> () -// BEFORE-NEXT: } {ast = #cir.vardecl.ast} +// BEFORE-NEXT: } {ast = #cir.var.decl.ast} // BEFORE-NEXT: } @@ -43,7 +43,7 @@ static Init __ioinit2(false); // AFTER-NEXT: cir.func private @__cxa_atexit(!cir.ptr)>>, !cir.ptr, !cir.ptr) // AFTER-NEXT: cir.func private @_ZN4InitC1Eb(!cir.ptr, !cir.bool) // AFTER-NEXT: cir.func private @_ZN4InitD1Ev(!cir.ptr) -// AFTER-NEXT: cir.global "private" internal @_ZL8__ioinit = #cir.zero : !ty_22Init22 {ast = #cir.vardecl.ast} +// AFTER-NEXT: cir.global "private" internal @_ZL8__ioinit = #cir.zero : !ty_22Init22 {ast = #cir.var.decl.ast} // AFTER-NEXT: cir.func internal private @__cxx_global_var_init() // AFTER-NEXT: %0 = cir.get_global @_ZL8__ioinit : cir.ptr // AFTER-NEXT: %1 = cir.const(#true) : !cir.bool @@ -55,7 +55,7 @@ static Init __ioinit2(false); // AFTER-NEXT: %6 = cir.get_global @__dso_handle : cir.ptr // AFTER-NEXT: cir.call @__cxa_atexit(%4, %5, %6) : (!cir.ptr)>>, !cir.ptr, !cir.ptr) -> () // AFTER-NEXT: cir.return -// AFTER: cir.global "private" internal @_ZL9__ioinit2 = #cir.zero : !ty_22Init22 {ast = #cir.vardecl.ast} +// AFTER: cir.global "private" internal @_ZL9__ioinit2 = #cir.zero : !ty_22Init22 {ast = #cir.var.decl.ast} // AFTER-NEXT: cir.func internal private @__cxx_global_var_init.1() // AFTER-NEXT: %0 = cir.get_global @_ZL9__ioinit2 : cir.ptr // AFTER-NEXT: %1 = cir.const(#false) : !cir.bool diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp index 55b1a4dd725b..07c5e7f70064 100644 --- a/clang/test/CIR/CodeGen/struct.cpp +++ b/clang/test/CIR/CodeGen/struct.cpp @@ -30,7 +30,7 @@ void yoyo(incomplete *i) {} // CHECK-DAG: !ty_22Bar22 = !cir.struct // CHECK-DAG: !ty_22Foo22 = !cir.struct -// CHECK-DAG: !ty_22Mandalore22 = !cir.struct, !s32i} #cir.recdecl.ast> +// CHECK-DAG: !ty_22Mandalore22 = !cir.struct, !s32i} #cir.record.decl.ast> // CHECK-DAG: !ty_22Adv22 = !cir.struct // CHECK-DAG: !ty_22Entry22 = !cir.struct, !cir.ptr)>>}> diff --git a/clang/test/CIR/CodeGen/union.cpp b/clang/test/CIR/CodeGen/union.cpp index 8892157a6824..f9b8db8ec158 100644 --- a/clang/test/CIR/CodeGen/union.cpp +++ b/clang/test/CIR/CodeGen/union.cpp @@ -6,10 +6,10 @@ typedef union { yolo y; struct { int lifecnt; }; } yolm; typedef union { yolo y; struct { int *lifecnt; int genpad; }; } yolm2; typedef union { yolo y; struct { bool life; int genpad; }; } yolm3; -// CHECK-DAG: !ty_22U23A3ADummy22 = !cir.struct -// CHECK-DAG: !ty_22anon221 = !cir.struct -// CHECK-DAG: !ty_22yolo22 = !cir.struct -// CHECK-DAG: !ty_22anon222 = !cir.struct, !s32i} #cir.recdecl.ast> +// CHECK-DAG: !ty_22U23A3ADummy22 = !cir.struct +// CHECK-DAG: !ty_22anon221 = !cir.struct +// CHECK-DAG: !ty_22yolo22 = !cir.struct +// CHECK-DAG: !ty_22anon222 = !cir.struct, !s32i} #cir.record.decl.ast> // CHECK-DAG: !ty_22yolm22 = !cir.struct // CHECK-DAG: !ty_22yolm322 = !cir.struct @@ -33,14 +33,14 @@ union U2 { float f; } s; } u2; -// CHECK-DAG: !cir.struct +// CHECK-DAG: !cir.struct // Should genereate unions without padding. union U3 { short b; U u; } u3; -// CHECK-DAG: !ty_22U322 = !cir.struct +// CHECK-DAG: !ty_22U322 = !cir.struct void m() { yolm q; diff --git a/clang/test/CIR/CodeGen/vtable-rtti.cpp b/clang/test/CIR/CodeGen/vtable-rtti.cpp index 35cc4e58d75e..6da37c786d2b 100644 --- a/clang/test/CIR/CodeGen/vtable-rtti.cpp +++ b/clang/test/CIR/CodeGen/vtable-rtti.cpp @@ -24,7 +24,7 @@ class B : public A // CHECK: ![[VTableTypeA:ty_.*]] = !cir.struct x 5>}> // Class A -// CHECK: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.recdecl.ast> +// CHECK: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.record.decl.ast> // Class B // CHECK: ![[ClassB:ty_.*]] = !cir.struct diff --git a/clang/test/CIR/IR/global.cir b/clang/test/CIR/IR/global.cir index 4ffda321f221..8ee44c5beeb0 100644 --- a/clang/test/CIR/IR/global.cir +++ b/clang/test/CIR/IR/global.cir @@ -3,7 +3,7 @@ !s8i = !cir.int !s32i = !cir.int !s64i = !cir.int -!ty_22Init22 = !cir.struct +!ty_22Init22 = !cir.struct module { cir.global external @a = #cir.int<3> : !s32i cir.global external @rgb = #cir.const_array<[#cir.int<0> : !s8i, #cir.int<-23> : !s8i, #cir.int<33> : !s8i] : !cir.array> diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index cd5d709e57a4..ce7eafd6a1e8 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -488,7 +488,7 @@ module { // ----- !s8i = !cir.int -!ty_22Init22 = !cir.struct +!ty_22Init22 = !cir.struct module { cir.global "private" internal @_ZL8__ioinit = ctor : !ty_22Init22 { } @@ -498,7 +498,7 @@ module { // ----- !s8i = !cir.int #true = #cir.bool : !cir.bool -!ty_22Init22 = !cir.struct +!ty_22Init22 = !cir.struct module { cir.func private @_ZN4InitC1Eb(!cir.ptr) cir.global "private" internal @_ZL8__ioinit = ctor : !ty_22Init22 { diff --git a/clang/test/CIR/IR/struct.cir b/clang/test/CIR/IR/struct.cir index aa0acce60abd..fb25d04533da 100644 --- a/clang/test/CIR/IR/struct.cir +++ b/clang/test/CIR/IR/struct.cir @@ -8,7 +8,7 @@ !ty_2222 = !cir.struct x 5>}> !ty_22221 = !cir.struct, !cir.ptr, !cir.ptr}> -!ty_22A22 = !cir.struct +!ty_22A22 = !cir.struct !ty_22i22 = !cir.struct !ty_22S22 = !cir.struct !ty_22S122 = !cir.struct diff --git a/clang/test/CIR/Lowering/array.cir b/clang/test/CIR/Lowering/array.cir index 3028835d521d..46ea393decd2 100644 --- a/clang/test/CIR/Lowering/array.cir +++ b/clang/test/CIR/Lowering/array.cir @@ -2,7 +2,7 @@ // RUN: cir-translate %s -cir-to-llvmir -o - | FileCheck %s -check-prefix=LLVM !s32i = !cir.int -!ty_22S22 = !cir.struct +!ty_22S22 = !cir.struct module { cir.func @foo() { @@ -26,10 +26,10 @@ module { // CHECK: %0 = llvm.mlir.undef : !llvm.array<2 x struct<"struct.S", (i32)>> // CHECK: %1 = llvm.mlir.undef : !llvm.struct<"struct.S", (i32)> // CHECK: %2 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %3 = llvm.insertvalue %2, %1[0] : !llvm.struct<"struct.S", (i32)> - // CHECK: %4 = llvm.insertvalue %3, %0[0] : !llvm.array<2 x struct<"struct.S", (i32)>> + // CHECK: %3 = llvm.insertvalue %2, %1[0] : !llvm.struct<"struct.S", (i32)> + // CHECK: %4 = llvm.insertvalue %3, %0[0] : !llvm.array<2 x struct<"struct.S", (i32)>> // CHECK: %5 = cir.llvmir.zeroinit : !llvm.struct<"struct.S", (i32)> - // CHECK: %6 = llvm.insertvalue %5, %4[1] : !llvm.array<2 x struct<"struct.S", (i32)>> + // CHECK: %6 = llvm.insertvalue %5, %4[1] : !llvm.array<2 x struct<"struct.S", (i32)>> // CHECK: llvm.return %6 : !llvm.array<2 x struct<"struct.S", (i32)>> // CHECK: } } diff --git a/clang/test/CIR/Lowering/globals.cir b/clang/test/CIR/Lowering/globals.cir index a6476ff2fe1d..9920c3a4a7f9 100644 --- a/clang/test/CIR/Lowering/globals.cir +++ b/clang/test/CIR/Lowering/globals.cir @@ -10,10 +10,10 @@ !u32i = !cir.int !u64i = !cir.int !u8i = !cir.int -!ty_22A22 = !cir.struct x 2>} #cir.recdecl.ast> -!ty_22Bar22 = !cir.struct -!ty_22StringStruct22 = !cir.struct, !cir.array, !cir.array} #cir.recdecl.ast> -!ty_22StringStructPtr22 = !cir.struct} #cir.recdecl.ast> +!ty_22A22 = !cir.struct x 2>} #cir.record.decl.ast> +!ty_22Bar22 = !cir.struct +!ty_22StringStruct22 = !cir.struct, !cir.array, !cir.array} #cir.record.decl.ast> +!ty_22StringStructPtr22 = !cir.struct} #cir.record.decl.ast> module { cir.global external @a = #cir.int<3> : !s32i diff --git a/clang/test/CIR/Lowering/struct.cir b/clang/test/CIR/Lowering/struct.cir index 7543154ea0e5..f68f96c0e72d 100644 --- a/clang/test/CIR/Lowering/struct.cir +++ b/clang/test/CIR/Lowering/struct.cir @@ -5,10 +5,10 @@ !u8i = !cir.int !u32i = !cir.int !ty_22S22 = !cir.struct -!ty_22S2A22 = !cir.struct -!ty_22S122 = !cir.struct} #cir.recdecl.ast> -!ty_22S222 = !cir.struct -!ty_22S322 = !cir.struct +!ty_22S2A22 = !cir.struct +!ty_22S122 = !cir.struct} #cir.record.decl.ast> +!ty_22S222 = !cir.struct +!ty_22S322 = !cir.struct module { cir.func @test() { diff --git a/clang/test/CIR/Lowering/unions.cir b/clang/test/CIR/Lowering/unions.cir index 3e303c377f7e..d2dbc4ca5f23 100644 --- a/clang/test/CIR/Lowering/unions.cir +++ b/clang/test/CIR/Lowering/unions.cir @@ -4,9 +4,9 @@ !s16i = !cir.int !s32i = !cir.int #true = #cir.bool : !cir.bool -!ty_22U122 = !cir.struct -!ty_22U222 = !cir.struct -!ty_22U322 = !cir.struct +!ty_22U122 = !cir.struct +!ty_22U222 = !cir.struct +!ty_22U322 = !cir.struct module { // Should lower union to struct with only the largest member. cir.global external @u1 = #cir.zero : !ty_22U122 diff --git a/clang/test/CIR/Lowering/variadics.cir b/clang/test/CIR/Lowering/variadics.cir index f533b54d0151..2c7c9acf5e25 100644 --- a/clang/test/CIR/Lowering/variadics.cir +++ b/clang/test/CIR/Lowering/variadics.cir @@ -5,7 +5,7 @@ !u32i = !cir.int !u8i = !cir.int -!ty_22__va_list_tag22 = !cir.struct, !cir.ptr} #cir.recdecl.ast> +!ty_22__va_list_tag22 = !cir.struct, !cir.ptr} #cir.record.decl.ast> module { cir.func @average(%arg0: !s32i, ...) -> !s32i {