-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[CIR][NFC] Refactor constant pointer l-value handling #144165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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.
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/144165.diff 1 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index c41ab54be09ca..c4380618a624b 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 (TypeInfoLValue TI = 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");
|
// 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only path that doesn't hit an errorNYI
call, and along with the convertTypeForMem
call above, it should correspond exactly to the previous implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
} | ||
|
||
// Handle typeid(T). | ||
if (TypeInfoLValue TI = base.dyn_cast<TypeInfoLValue>()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: TI
is unused
if (base.dyn_cast<TypeInfoLValue>()) {
}
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.