[clang] b5c6245 - [CIR][NFC] Refactor constant pointer l-value handling (#144165)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 16 11:26:26 PDT 2025
Author: Andy Kaylor
Date: 2025-06-16T11:26:23-07:00
New Revision: b5c6245cb46354923940b95a89213fa0924e5c5f
URL: https://github.com/llvm/llvm-project/commit/b5c6245cb46354923940b95a89213fa0924e5c5f
DIFF: https://github.com/llvm/llvm-project/commit/b5c6245cb46354923940b95a89213fa0924e5c5f.diff
LOG: [CIR][NFC] Refactor constant pointer l-value handling (#144165)
This change introduces a ConstantLValueEmitter class, which will be
needed for emitting CIR for non-trivial constant pointers. This change
introduces the class with most branches reaching an NYI diagnostic. The
only path that is currently implemented is the case where an absolute
pointer (usually a null pointer) is emitted. This corresponds to the
existing handler for emitting l-value constants.
Added:
Modified:
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index c41ab54be09ca..1976742d4039e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -329,6 +329,222 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
return {};
}
+//===----------------------------------------------------------------------===//
+// ConstantLValueEmitter
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// A struct which can be used to peephole certain kinds of finalization
+/// that normally happen during l-value emission.
+struct ConstantLValue {
+ llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
+ bool hasOffsetApplied;
+
+ ConstantLValue(std::nullptr_t) : value(nullptr), hasOffsetApplied(false) {}
+ ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
+};
+
+/// A helper class for emitting constant l-values.
+class ConstantLValueEmitter
+ : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {
+ CIRGenModule &cgm;
+ ConstantEmitter &emitter;
+ const APValue &value;
+ QualType destType;
+
+ // Befriend StmtVisitorBase so that we don't have to expose Visit*.
+ friend StmtVisitorBase;
+
+public:
+ ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
+ QualType destType)
+ : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
+
+ mlir::Attribute tryEmit();
+
+private:
+ mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
+ ConstantLValue tryEmitBase(const APValue::LValueBase &base);
+
+ ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }
+ ConstantLValue VisitConstantExpr(const ConstantExpr *e);
+ ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);
+ ConstantLValue VisitStringLiteral(const StringLiteral *e);
+ ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);
+ ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);
+ ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);
+ ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);
+ ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);
+ ConstantLValue VisitCallExpr(const CallExpr *e);
+ ConstantLValue VisitBlockExpr(const BlockExpr *e);
+ ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);
+ ConstantLValue
+ VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
+};
+
+} // namespace
+
+mlir::Attribute ConstantLValueEmitter::tryEmit() {
+ const APValue::LValueBase &base = value.getLValueBase();
+
+ // The destination type should be a pointer or reference
+ // type, but it might also be a cast thereof.
+ //
+ // FIXME: the chain of casts required should be reflected in the APValue.
+ // We need this in order to correctly handle things like a ptrtoint of a
+ // non-zero null pointer and addrspace casts that aren't trivially
+ // represented in LLVM IR.
+ mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
+ assert(mlir::isa<cir::PointerType>(destTy));
+
+ // If there's no base at all, this is a null or absolute pointer,
+ // possibly cast back to an integer type.
+ if (!base)
+ return tryEmitAbsolute(destTy);
+
+ // Otherwise, try to emit the base.
+ ConstantLValue result = tryEmitBase(base);
+
+ // If that failed, we're done.
+ llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
+ if (!value)
+ return {};
+
+ // Apply the offset if necessary and not already done.
+ if (!result.hasOffsetApplied) {
+ cgm.errorNYI("ConstantLValueEmitter: apply offset");
+ return {};
+ }
+
+ // Convert to the appropriate type; this could be an lvalue for
+ // an integer. FIXME: performAddrSpaceCast
+ if (mlir::isa<cir::PointerType>(destTy)) {
+ if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))
+ return attr;
+ cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");
+ return {};
+ }
+
+ cgm.errorNYI("ConstantLValueEmitter: other?");
+ return {};
+}
+
+/// Try to emit an absolute l-value, such as a null pointer or an integer
+/// bitcast to pointer type.
+mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
+ // If we're producing a pointer, this is easy.
+ auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
+ return cgm.getBuilder().getConstPtrAttr(
+ destPtrTy, value.getLValueOffset().getQuantity());
+}
+
+ConstantLValue
+ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
+ // Handle values.
+ if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {
+ // The constant always points to the canonical declaration. We want to look
+ // at properties of the most recent declaration at the point of emission.
+ d = cast<ValueDecl>(d->getMostRecentDecl());
+
+ if (d->hasAttr<WeakRefAttr>()) {
+ cgm.errorNYI(d->getSourceRange(),
+ "ConstantLValueEmitter: emit pointer base for weakref");
+ return {};
+ }
+
+ if (auto *fd = dyn_cast<FunctionDecl>(d)) {
+ cgm.errorNYI(fd->getSourceRange(),
+ "ConstantLValueEmitter: function decl");
+ return {};
+ }
+
+ if (auto *vd = dyn_cast<VarDecl>(d)) {
+ cgm.errorNYI(vd->getSourceRange(), "ConstantLValueEmitter: var decl");
+ return {};
+ }
+ }
+
+ // Handle typeid(T).
+ if (base.dyn_cast<TypeInfoLValue>()) {
+ cgm.errorNYI("ConstantLValueEmitter: typeid");
+ return {};
+ }
+
+ // Otherwise, it must be an expression.
+ return Visit(base.get<const Expr *>());
+}
+
+ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: compound literal");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: string literal");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {
+ cgm.errorNYI(e->getSourceRange(),
+ "ConstantLValueEmitter: objc string literal");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: predefined expr");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");
+ return {};
+}
+
+ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");
+ return {};
+}
+
+ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");
+ return {};
+}
+
+ConstantLValue
+ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {
+ cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: cxx typeid expr");
+ return {};
+}
+
+ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *e) {
+ cgm.errorNYI(e->getSourceRange(),
+ "ConstantLValueEmitter: materialize temporary expr");
+ return {};
+}
+
//===----------------------------------------------------------------------===//
// ConstantEmitter
//===----------------------------------------------------------------------===//
@@ -556,23 +772,8 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
return {};
}
- case APValue::LValue: {
-
- if (value.getLValueBase()) {
- cgm.errorNYI("non-null pointer initialization");
- } else {
-
- mlir::Type desiredType = cgm.convertType(destType);
- if (const cir::PointerType ptrType =
- mlir::dyn_cast<cir::PointerType>(desiredType)) {
- return builder.getConstPtrAttr(ptrType,
- value.getLValueOffset().getQuantity());
- } else {
- llvm_unreachable("non-pointer variable initialized with a pointer");
- }
- }
- return {};
- }
+ case APValue::LValue:
+ return ConstantLValueEmitter(*this, value, destType).tryEmit();
case APValue::Struct:
case APValue::Union:
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate struct or union");
More information about the cfe-commits
mailing list