llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) <details> <summary>Changes</summary> This change adds undef handling that was needed to enable global lambdas. There was no lambda-specific code needed, but the global lambda handling needed to initialize a global with an undef value. [CIR] Handle undef init of struct This adds handling for a case where Clang initializes a struct to undef with a constant copy. This required adding support for undef constants and lowering undef attributes to LLVM IR. --- Full diff: https://github.com/llvm/llvm-project/pull/169721.diff 3 Files Affected: - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+6) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+13-3) - (modified) clang/test/CIR/CodeGen/lambda.cpp (+33) ``````````diff diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 6bf543cf794b7..92fd591e3a37d 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -330,6 +330,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, "zero expects struct, array, vector, or complex type"); } + if (isa<cir::UndefAttr>(attrType)) { + if (!::mlir::isa<cir::VoidType>(opType)) + return success(); + return op->emitOpError("undef expects non-void type"); + } + if (mlir::isa<cir::BoolAttr>(attrType)) { if (!mlir::isa<cir::BoolType>(opType)) return op->emitOpError("result type (") diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index cd923a15af132..9e62317bff5f6 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -240,7 +240,7 @@ class CIRAttrToValue { .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr, cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr, cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr, - cir::VTableAttr, cir::ZeroAttr>( + cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>( [&](auto attrT) { return visitCirAttr(attrT); }) .Default([&](auto attrT) { return mlir::Value(); }); } @@ -254,6 +254,7 @@ class CIRAttrToValue { mlir::Value visitCirAttr(cir::ConstVectorAttr attr); mlir::Value visitCirAttr(cir::GlobalViewAttr attr); mlir::Value visitCirAttr(cir::TypeInfoAttr attr); + mlir::Value visitCirAttr(cir::UndefAttr attr); mlir::Value visitCirAttr(cir::VTableAttr attr); mlir::Value visitCirAttr(cir::ZeroAttr attr); @@ -591,6 +592,13 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) { return result; } +/// UndefAttr visitor. +mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) { + mlir::Location loc = parentOp->getLoc(); + return mlir::LLVM::UndefOp::create( + rewriter, loc, converter->convertType(undefAttr.getType())); +} + // VTableAttr visitor. mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) { mlir::Type llvmTy = converter->convertType(vtableArr.getType()); @@ -2048,7 +2056,8 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal( // TODO: Generalize this handling when more types are needed here. assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr, cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr, - cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(init))); + cir::TypeInfoAttr, cir::VTableAttr, cir::UndefAttr, + cir::ZeroAttr>(init))); // TODO(cir): once LLVM's dialect has proper equivalent attributes this // should be updated. For now, we use a custom op to initialize globals @@ -2106,7 +2115,8 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( } else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr, cir::ConstRecordAttr, cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr, - cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>( + cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, + cir::ZeroAttr>( init.value())) { // TODO(cir): once LLVM's dialect has proper equivalent attributes this // should be updated. For now, we use a custom op to initialize globals diff --git a/clang/test/CIR/CodeGen/lambda.cpp b/clang/test/CIR/CodeGen/lambda.cpp index 91380b9bea296..84d446727d6e3 100644 --- a/clang/test/CIR/CodeGen/lambda.cpp +++ b/clang/test/CIR/CodeGen/lambda.cpp @@ -8,6 +8,39 @@ // We declare anonymous record types to represent lambdas. Rather than trying to // to match the declarations, we establish variables for these when they are used. +auto global_lambda = [](){}; +void use_global_lambda() { + global_lambda(); +} + +// CIR: cir.global "private" internal dso_local @global_lambda = #cir.undef : ![[REC_LAM_GLOBAL_LAMBDA:.*]] {alignment = 1 : i64} +// CIR: cir.func lambda internal private dso_local @_ZNK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]> {{.*}}) +// CIR: %[[THIS:.*]] = cir.alloca !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>, !cir.ptr<!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>>, ["this", init] +// CIR: cir.store %[[THIS_ARG]], %[[THIS]] +// CIR: cir.load %[[THIS]] +// +// CIR: cir.func {{.*}} @_Z17use_global_lambdav() +// CIR: %[[LAMBDA:.*]] = cir.get_global @global_lambda : !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]> +// CIR: cir.call @_ZNK3$_0clEv(%[[LAMBDA]]) : (!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>) -> () + +// LLVM: @global_lambda = internal global %class.anon.0 undef, align 1 +// LLVM: define internal void @"_ZNK3$_0clEv"(ptr %[[THIS_ARG:.*]]) +// LLVM: %[[THIS_ADDR:.*]] = alloca ptr +// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]] +// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]] +// +// LLVM: define dso_local void @_Z17use_global_lambdav() +// LLVM: call void @"_ZNK3$_0clEv"(ptr @global_lambda) + +// OGCG: @global_lambda = internal global %class.anon undef, align 1 +// OGCG: define dso_local void @_Z17use_global_lambdav() +// OGCG: call void @"_ZNK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) @global_lambda) +// +// OGCG: define internal void @"_ZNK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]]) +// OGCG: %[[THIS_ADDR:.*]] = alloca ptr +// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]] +// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]] + void fn() { auto a = [](){}; a(); `````````` </details> https://github.com/llvm/llvm-project/pull/169721 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
