Skip to content

Commit db4418b

Browse files
andykaylorgithub-actions[bot]
authored andcommitted
Automerge: [CIR] Add undef handling to enable global lambdas (#169721)
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.
2 parents c12bcfe + 20d95c8 commit db4418b

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
330330
"zero expects struct, array, vector, or complex type");
331331
}
332332

333+
if (mlir::isa<cir::UndefAttr>(attrType)) {
334+
if (!mlir::isa<cir::VoidType>(opType))
335+
return success();
336+
return op->emitOpError("undef expects non-void type");
337+
}
338+
333339
if (mlir::isa<cir::BoolAttr>(attrType)) {
334340
if (!mlir::isa<cir::BoolType>(opType))
335341
return op->emitOpError("result type (")

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ class CIRAttrToValue {
240240
.Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
241241
cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
242242
cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
243-
cir::VTableAttr, cir::ZeroAttr>(
243+
cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
244244
[&](auto attrT) { return visitCirAttr(attrT); })
245245
.Default([&](auto attrT) { return mlir::Value(); });
246246
}
@@ -254,6 +254,7 @@ class CIRAttrToValue {
254254
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
255255
mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
256256
mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
257+
mlir::Value visitCirAttr(cir::UndefAttr attr);
257258
mlir::Value visitCirAttr(cir::VTableAttr attr);
258259
mlir::Value visitCirAttr(cir::ZeroAttr attr);
259260

@@ -591,6 +592,13 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
591592
return result;
592593
}
593594

595+
/// UndefAttr visitor.
596+
mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
597+
mlir::Location loc = parentOp->getLoc();
598+
return mlir::LLVM::UndefOp::create(
599+
rewriter, loc, converter->convertType(undefAttr.getType()));
600+
}
601+
594602
// VTableAttr visitor.
595603
mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
596604
mlir::Type llvmTy = converter->convertType(vtableArr.getType());
@@ -2046,9 +2054,11 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
20462054
cir::GlobalOp op, mlir::Attribute init,
20472055
mlir::ConversionPatternRewriter &rewriter) const {
20482056
// TODO: Generalize this handling when more types are needed here.
2049-
assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2050-
cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2051-
cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
2057+
assert(
2058+
(isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2059+
cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2060+
cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2061+
init)));
20522062

20532063
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
20542064
// should be updated. For now, we use a custom op to initialize globals
@@ -2106,8 +2116,8 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
21062116
} else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
21072117
cir::ConstRecordAttr, cir::ConstPtrAttr,
21082118
cir::ConstComplexAttr, cir::GlobalViewAttr,
2109-
cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(
2110-
init.value())) {
2119+
cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2120+
cir::ZeroAttr>(init.value())) {
21112121
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
21122122
// should be updated. For now, we use a custom op to initialize globals
21132123
// to the appropriate value.

clang/test/CIR/CodeGen/lambda.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,39 @@
88
// We declare anonymous record types to represent lambdas. Rather than trying to
99
// to match the declarations, we establish variables for these when they are used.
1010

11+
auto global_lambda = [](){};
12+
void use_global_lambda() {
13+
global_lambda();
14+
}
15+
16+
// CIR: cir.global "private" internal dso_local @global_lambda = #cir.undef : ![[REC_LAM_GLOBAL_LAMBDA:.*]] {alignment = 1 : i64}
17+
// CIR: cir.func lambda internal private dso_local @_ZNK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]> {{.*}})
18+
// CIR: %[[THIS:.*]] = cir.alloca !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>, !cir.ptr<!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>>, ["this", init]
19+
// CIR: cir.store %[[THIS_ARG]], %[[THIS]]
20+
// CIR: cir.load %[[THIS]]
21+
//
22+
// CIR: cir.func {{.*}} @_Z17use_global_lambdav()
23+
// CIR: %[[LAMBDA:.*]] = cir.get_global @global_lambda : !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>
24+
// CIR: cir.call @_ZNK3$_0clEv(%[[LAMBDA]]) : (!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>) -> ()
25+
26+
// LLVM: @global_lambda = internal global %[[REC_LAM_GLOBAL_LAMBDA:.*]] undef, align 1
27+
// LLVM: define internal void @"_ZNK3$_0clEv"(ptr %[[THIS_ARG:.*]])
28+
// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
29+
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
30+
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
31+
//
32+
// LLVM: define dso_local void @_Z17use_global_lambdav()
33+
// LLVM: call void @"_ZNK3$_0clEv"(ptr @global_lambda)
34+
35+
// OGCG: @global_lambda = internal global %[[REC_LAM_GLOBAL_LAMBDA:.*]] undef, align 1
36+
// OGCG: define dso_local void @_Z17use_global_lambdav()
37+
// OGCG: call void @"_ZNK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) @global_lambda)
38+
//
39+
// OGCG: define internal void @"_ZNK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]])
40+
// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
41+
// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
42+
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
43+
1144
void fn() {
1245
auto a = [](){};
1346
a();

0 commit comments

Comments
 (0)