[clang] [CIR] Upstream support for references (PR #138001)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 30 10:49:57 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Andy Kaylor (andykaylor)
<details>
<summary>Changes</summary>
This adds basic support for handling reference values.
---
Full diff: https://github.com/llvm/llvm-project/pull/138001.diff
4 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+35-1)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+5)
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+10)
- (modified) clang/test/CIR/CodeGen/basic.cpp (+17)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index ff14798b9d34c..080209ca04b4c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -439,7 +439,13 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: static local");
}
- return makeAddrLValue(addr, ty, AlignmentSource::Type);
+ // Drill into reference types.
+ LValue lv =
+ vd->getType()->isReferenceType()
+ ? emitLoadOfReferenceLValue(addr, getLoc(e->getSourceRange()),
+ vd->getType(), AlignmentSource::Decl)
+ : makeAddrLValue(addr, ty, AlignmentSource::Decl);
+ return lv;
}
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
@@ -1065,6 +1071,34 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
return addr;
}
+Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc,
+ LValueBaseInfo *pointeeBaseInfo) {
+ if (refLVal.isVolatile())
+ cgm.errorNYI(loc, "load of volatile reference");
+
+ cir::LoadOp load =
+ builder.create<cir::LoadOp>(loc, refLVal.getAddress().getElementType(),
+ refLVal.getAddress().getPointer());
+
+ assert(!cir::MissingFeatures::opTBAA());
+
+ QualType pointeeType = refLVal.getType()->getPointeeType();
+ CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
+ return Address(load, convertTypeForMem(pointeeType), align);
+}
+
+LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,
+ mlir::Location loc,
+ QualType refTy,
+ AlignmentSource source) {
+ LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
+ LValueBaseInfo pointeeBaseInfo;
+ assert(!cir::MissingFeatures::opTBAA());
+ Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
+ return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
+ pointeeBaseInfo);
+}
+
mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
clang::QualType qt) {
mlir::Type t = convertType(qt);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 592d39930089d..b4e1d24e0feda 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -560,6 +560,11 @@ class CIRGenFunction : public CIRGenTypeCache {
/// returning the rvalue.
RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
+ Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
+ LValueBaseInfo *pointeeBaseInfo);
+ LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
+ QualType refTy, AlignmentSource source);
+
/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation. The l-value must be a simple
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index de8ea0bd92158..98c9398fd4d94 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -381,6 +381,16 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
break;
}
+ case Type::LValueReference:
+ case Type::RValueReference: {
+ const ReferenceType *refTy = cast<ReferenceType>(ty);
+ QualType elemTy = refTy->getPointeeType();
+ auto pointeeType = convertTypeForMem(elemTy);
+ resultType = builder.getPointerTo(pointeeType);
+ assert(resultType && "Cannot get pointer type?");
+ break;
+ }
+
case Type::Pointer: {
const PointerType *ptrTy = cast<PointerType>(ty);
QualType elemTy = ptrTy->getPointeeType();
diff --git a/clang/test/CIR/CodeGen/basic.cpp b/clang/test/CIR/CodeGen/basic.cpp
index 1f289e905dd09..cf3fab5de510e 100644
--- a/clang/test/CIR/CodeGen/basic.cpp
+++ b/clang/test/CIR/CodeGen/basic.cpp
@@ -102,3 +102,20 @@ size_type max_size() {
// CHECK: %3 = cir.cast(integral, %2 : !s32i), !u64i
// CHECK: %4 = cir.const #cir.int<8> : !u64i
// CHECK: %5 = cir.binop(div, %3, %4) : !u64i
+
+void ref_arg(int &x) {
+ int y = x;
+ x = 3;
+}
+
+// CHECK: cir.func @_Z7ref_argRi(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}})
+// CHECK: %[[X_REF_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init, const] {alignment = 8 : i64}
+// CHECK: %[[Y_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init] {alignment = 4 : i64}
+// CHECK: cir.store %[[ARG]], %[[X_REF_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
+// CHECK: %[[X_REF:.*]] = cir.load %[[X_REF_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CHECK: %[[Y:.*]] = cir.load %[[X_REF]] : !cir.ptr<!s32i>, !s32i
+// CHECK: cir.store %[[Y]], %[[Y_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CHECK: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
+// CHECK: %[[X_REF:.*]] = cir.load %[[X_REF_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CHECK: cir.store %[[THREE]], %[[X_REF]] : !s32i, !cir.ptr<!s32i>
+// CHECK: cir.return
``````````
</details>
https://github.com/llvm/llvm-project/pull/138001
More information about the cfe-commits
mailing list