llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) <details> <summary>Changes</summary> This adds the minimum support for C++ data member pointer variables. --- Patch is 37.69 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170939.diff 26 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.h (+1) - (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+51) - (modified) clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td (+9-1) - (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+31-1) - (modified) clang/include/clang/CIR/MissingFeatures.h (+5) - (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+5) - (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+2-5) - (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+20) - (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+2) - (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+15) - (modified) clang/lib/CIR/Dialect/IR/CIRAttrs.cpp (+32) - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+6) - (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+20) - (modified) clang/lib/CIR/Dialect/Transforms/CMakeLists.txt (+3) - (added) clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp (+20) - (added) clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h (+55) - (added) clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt (+20) - (added) clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp (+90) - (added) clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp (+87) - (added) clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h (+55) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt (+5) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+31-3) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+2) - (added) clang/test/CIR/CodeGen/pointer-to-data-member.cpp (+35) - (added) clang/test/CIR/IR/invalid-data-member.cir (+27) - (modified) clang/utils/TableGen/CIRLoweringEmitter.cpp (+5-2) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h index 03a6a97dc8c2e..858d4d6350bed 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h @@ -35,6 +35,7 @@ namespace cir { class ArrayType; class BoolType; class ComplexType; +class DataMemberType; class IntType; class MethodType; class PointerType; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 98d4636dafc29..c0279a0b20670 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -447,6 +447,57 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> { }]; } +//===----------------------------------------------------------------------===// +// DataMemberAttr +//===----------------------------------------------------------------------===// + +def CIR_DataMemberAttr : CIR_Attr<"DataMember", "data_member", [ + TypedAttrInterface +]> { + let summary = "Holds a constant data member pointer value"; + let parameters = (ins AttributeSelfTypeParameter< + "", "cir::DataMemberType">:$type, + OptionalParameter< + "std::optional<unsigned>">:$member_index); + let description = [{ + A data member attribute is a literal attribute that represents a constant + pointer-to-data-member value. + + The `member_index` parameter represents the index of the pointed-to member + within its containing record. It is an optional parameter; lack of this + parameter indicates a null pointer-to-data-member value. + + Example: + ``` + #ptr = #cir.data_member<1> : !cir.data_member<!s32i in !rec_22Point22> + + #null = #cir.data_member<null> : !cir.data_member<!s32i in !rec_22Point22> + ``` + }]; + + let builders = [ + AttrBuilderWithInferredContext<(ins "cir::DataMemberType":$type), [{ + return $_get(type.getContext(), type, std::nullopt); + }]>, + AttrBuilderWithInferredContext<(ins "cir::DataMemberType":$type, + "unsigned":$member_index), [{ + return $_get(type.getContext(), type, member_index); + }]>, + ]; + + let genVerifyDecl = 1; + + let assemblyFormat = [{ + `<` ($member_index^):(`null`)? `>` + }]; + + let extraClassDeclaration = [{ + bool isNullPtr() const { + return !getMemberIndex().has_value(); + } + }]; +} + //===----------------------------------------------------------------------===// // GlobalViewAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td index ddca98eac93ab..89762249ed0c4 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td @@ -309,6 +309,13 @@ def CIR_AnyFloatOrVecOfFloatType let cppFunctionName = "isFPOrVectorOfFPType"; } +//===----------------------------------------------------------------------===// +// Data member type predicates +//===----------------------------------------------------------------------===// + +def CIR_AnyDataMemberType : CIR_TypeBase<"::cir::DataMemberType", + "data member type">; + //===----------------------------------------------------------------------===// // VPtr type predicates //===----------------------------------------------------------------------===// @@ -322,7 +329,8 @@ def CIR_PtrToVPtr : CIR_PtrToType<CIR_AnyVPtrType>; //===----------------------------------------------------------------------===// defvar CIR_ScalarTypes = [ - CIR_AnyBoolType, CIR_AnyIntType, CIR_AnyFloatType, CIR_AnyPtrType + CIR_AnyBoolType, CIR_AnyIntType, CIR_AnyFloatType, CIR_AnyPtrType, + CIR_AnyDataMemberType, CIR_AnyVPtrType ]; def CIR_AnyScalarType : AnyTypeOf<CIR_ScalarTypes, "cir scalar type"> { diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 3e062add6633a..59b97f0c6d39a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -305,6 +305,36 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ }]; } +//===----------------------------------------------------------------------===// +// CIR_DataMemberType +//===----------------------------------------------------------------------===// + +def CIR_DataMemberType : CIR_Type<"DataMember", "data_member", + [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>] +> { + let summary = "CIR type that represents a pointer-to-data-member in C++"; + let description = [{ + `cir.data_member` models a pointer-to-data-member in C++. Values of this + type are essentially offsets of the pointed-to member within one of its + containing record. + }]; + + let parameters = (ins "mlir::Type":$member_ty, + "cir::RecordType":$class_ty); + + let builders = [ + TypeBuilderWithInferredContext<(ins + "mlir::Type":$member_ty, "cir::RecordType":$class_ty + ), [{ + return $_get(member_ty.getContext(), member_ty, class_ty); + }]>, + ]; + + let assemblyFormat = [{ + `<` $member_ty `in` $class_ty `>` + }]; +} + //===----------------------------------------------------------------------===// // CIR_VPtrType //===----------------------------------------------------------------------===// @@ -693,7 +723,7 @@ def CIRRecordType : Type< def CIR_AnyType : AnyTypeOf<[ CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType, CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType, - CIR_ComplexType, CIR_VPtrType + CIR_ComplexType, CIR_VPtrType, CIR_DataMemberType ]>; #endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index b8df0528ea18d..51d18750e72ac 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -189,6 +189,10 @@ struct MissingFeatures { static bool globalCtorLexOrder() { return false; } static bool globalCtorAssociatedData() { return false; } + // LowerModule handling + static bool lowerModuleCodeGenOpts() { return false; } + static bool lowerModuleLangOpts() { return false; } + // Misc static bool aarch64SIMDIntrinsics() { return false; } static bool aarch64SMEIntrinsics() { return false; } @@ -293,6 +297,7 @@ struct MissingFeatures { static bool lowerModeOptLevel() { return false; } static bool loweringPrepareX86CXXABI() { return false; } static bool loweringPrepareAArch64XXABI() { return false; } + static bool makeTripleAlwaysPresent() { return false; } static bool maybeHandleStaticInExternC() { return false; } static bool mergeAllConstants() { return false; } static bool metaDataNode() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 85b38120169fd..bf13eeeaea60a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -189,6 +189,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return getType<cir::RecordType>(nameAttr, kind); } + cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, + unsigned memberIndex) { + return cir::DataMemberAttr::get(ty, memberIndex); + } + // Return true if the value is a null constant such as null pointer, (+0.0) // for floating-point or zero initializer bool isNullValue(mlir::Attribute attr) const { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 3e9d3db768bea..c6f88c4f1f627 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -640,11 +640,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { } mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) { - if (llvm::isa<MemberPointerType>(e->getType())) { - cgf.cgm.errorNYI(e->getSourceRange(), "Address of member pointer"); - return builder.getNullPtr(cgf.convertType(e->getType()), - cgf.getLoc(e->getExprLoc())); - } + if (llvm::isa<MemberPointerType>(e->getType())) + return cgf.cgm.emitMemberPointerConstant(e); return cgf.emitLValue(e->getSubExpr()).getPointer(); } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 1d8e4a3b444ee..281418848c351 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1464,6 +1464,26 @@ void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e, "emitExplicitCastExprType"); } +mlir::Value CIRGenModule::emitMemberPointerConstant(const UnaryOperator *e) { + assert(!cir::MissingFeatures::cxxABI()); + + mlir::Location loc = getLoc(e->getSourceRange()); + + const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl(); + + // A member function pointer. + if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) { + errorNYI(e->getSourceRange(), "emitMemberPointerConstant: method pointer"); + return {}; + } + + // Otherwise, a member data pointer. + auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType())); + const auto *fieldDecl = cast<FieldDecl>(decl); + return cir::ConstantOp::create( + builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex())); +} + void CIRGenModule::emitDeclContext(const DeclContext *dc) { for (Decl *decl : dc->decls()) { // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index d7aee8ebf4d7a..f167102864893 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -481,6 +481,8 @@ class CIRGenModule : public CIRGenTypeCache { /// the given type. This is usually, but not always, an LLVM null constant. mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record); + mlir::Value emitMemberPointerConstant(const UnaryOperator *e); + llvm::StringRef getMangledName(clang::GlobalDecl gd); void emitTentativeDefinition(const VarDecl *d); diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index efc2c6c0ba500..da15b3626b349 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -481,6 +481,21 @@ mlir::Type CIRGenTypes::convertType(QualType type) { break; } + case Type::MemberPointer: { + const auto *mpt = cast<MemberPointerType>(ty); + + mlir::Type memberTy = convertType(mpt->getPointeeType()); + auto clsTy = mlir::cast<cir::RecordType>( + convertType(QualType(mpt->getQualifier().getAsType(), 0))); + if (mpt->isMemberDataPointer()) { + resultType = cir::DataMemberType::get(memberTy, clsTy); + } else { + assert(!cir::MissingFeatures::methodType()); + cgm.errorNYI(SourceLocation(), "MethodType"); + } + break; + } + case Type::FunctionNoProto: case Type::FunctionProto: resultType = convertFunctionTypeInternal(type); diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index ee296f171e0d9..59d7765198f9e 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -269,6 +269,38 @@ ConstComplexAttr::verify(function_ref<InFlightDiagnostic()> emitError, return success(); } +//===----------------------------------------------------------------------===// +// DataMemberAttr definitions +//===----------------------------------------------------------------------===// + +LogicalResult +DataMemberAttr::verify(function_ref<InFlightDiagnostic()> emitError, + cir::DataMemberType ty, + std::optional<unsigned> memberIndex) { + // DataMemberAttr without a given index represents a null value. + if (!memberIndex.has_value()) + return success(); + + cir::RecordType recTy = ty.getClassTy(); + if (recTy.isIncomplete()) + return emitError() + << "incomplete 'cir.record' cannot be used to build a non-null " + "data member pointer"; + + unsigned memberIndexValue = memberIndex.value(); + if (memberIndexValue >= recTy.getNumElements()) + return emitError() + << "member index of a #cir.data_member attribute is out of range"; + + mlir::Type memberTy = recTy.getMembers()[memberIndexValue]; + if (memberTy != ty.getMemberTy()) + return emitError() + << "member type of a #cir.data_member attribute must match the " + "attribute type"; + + return success(); +} + //===----------------------------------------------------------------------===// // CIR ConstArrayAttr //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 396d97ddd794e..56b69ec81dc34 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -357,6 +357,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, return success(); } + if (isa<cir::DataMemberAttr>(attrType)) { + // More detailed type verifications are already done in + // DataMemberAttr::verify. Don't need to repeat here. + return success(); + } + if (isa<cir::ZeroAttr>(attrType)) { if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>( opType)) diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index bb87056048ec5..9a37a4f4e3996 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -750,6 +750,26 @@ BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout, return 1; } +//===----------------------------------------------------------------------===// +// DataMemberType Definitions +//===----------------------------------------------------------------------===// + +llvm::TypeSize +DataMemberType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + // FIXME: consider size differences under different ABIs + assert(!MissingFeatures::cxxABI()); + return llvm::TypeSize::getFixed(64); +} + +uint64_t +DataMemberType::getABIAlignment(const ::mlir::DataLayout &dataLayout, + ::mlir::DataLayoutEntryListRef params) const { + // FIXME: consider alignment differences under different ABIs + assert(!MissingFeatures::cxxABI()); + return 8; +} + //===----------------------------------------------------------------------===// // VPtrType Definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt index 3fc5b06b74e4d..e3b7106c1d6b9 100644 --- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(TargetLowering) + add_clang_library(MLIRCIRTransforms CIRCanonicalize.cpp CIRSimplify.cpp @@ -21,4 +23,5 @@ add_clang_library(MLIRCIRTransforms MLIRCIR MLIRCIRInterfaces + MLIRCIRTargetLowering ) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp new file mode 100644 index 0000000000000..86cf7ebdc8f50 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp @@ -0,0 +1,20 @@ +//===- CIRCXXABI.cpp ------------------------------------------------------===// +// +// 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 partially mimics clang/lib/CodeGen/CGCXXABI.cpp. The queries are +// adapted to operate on the CIR dialect, however. +// +//===----------------------------------------------------------------------===// + +#include "CIRCXXABI.h" + +namespace cir { + +CIRCXXABI::~CIRCXXABI() {} + +} // namespace cir diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h new file mode 100644 index 0000000000000..fa14375a6edb8 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h @@ -0,0 +1,55 @@ +//===----- CIRCXXABI.h - Interface to C++ ABIs for CIR Dialect --*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file partially mimics the CodeGen/CGCXXABI.h class. The main difference +// is that this is adapted to operate on the CIR dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRCXXABI_H +#define CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRCXXABI_H + +#include "mlir/Transforms/DialectConversion.h" +#include "clang/CIR/Dialect/IR/CIRTypes.h" + +namespace cir { + +// Forward declarations. +class LowerModule; + +class CIRCXXABI { + friend class LowerModule; + +protected: + LowerModule &lm; + + CIRCXXABI(LowerModule &lm) : lm(lm) {} + +public: + virtual ~CIRCXXABI(); + + /// Lower the given data member pointer type to its ABI type. The returned + /// type is also a CIR type. + virtual mlir::Type + lowerDataMemberType(cir::DataMemberType type, + const mlir::TypeConverter &typeConverter) const = 0; + + /// Lower the given data member pointer constant to a constant of the ABI + /// type. The returned constant is represented as an attribute as well. + virtual mlir::TypedAttr + lowerDataMemberConstant(cir::DataMemberAttr attr, + const mlir::DataLayout &layout, + const mlir::TypeConverter &typeConverter) const = 0; +}; + +/// Creates an Itanium-family ABI. +CIRCXXABI *createItaniumCXXABI(LowerModule &lm); + +} // namespace cir + +#endif // CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRCXXABI_H diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt new file mode 100644 index 0000000000000..158c42e729536 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt @@ -0,0 +1,20 @@ +add_clang_library(MLIRCIRTargetLowering + CIRCXXABI.cpp + LowerModule.cpp + LowerItaniumCXXABI.cpp + + DEPENDS + clangBasic + + LINK_COMPONENTS + TargetParser + + LINK_LIBS PUBLIC + + clangBasic + MLIRIR + MLIRPass + MLIRDLTIDialect + MLIRCIR + MLIRCIRInterfaces +) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp new file mode 100644 index 0000000000000..1e2c9b68f3a6e --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp @@ -0,0 +1,90 @@ +//===---- LowerItaniumCXXABI.cpp - Emit CIR code Itanium-specific code ---===// +// +// 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 provides CIR lowering logic targeting the Itanium C++ ABI. The class in +// this file generates records that follow the Itanium C++ ABI, which is +// documented at: +// https://itanium-cxx-abi.github.io/cxx-abi/abi.html +// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html +// +// It also supports the closely-related ARM ABI, doc... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/170939 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
