Skip to content

Commit b5c6245

Browse files
authored
[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.
1 parent 539cf82 commit b5c6245

File tree

1 file changed

+218
-17
lines changed

1 file changed

+218
-17
lines changed

clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp

Lines changed: 218 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,222 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
329329
return {};
330330
}
331331

332+
//===----------------------------------------------------------------------===//
333+
// ConstantLValueEmitter
334+
//===----------------------------------------------------------------------===//
335+
336+
namespace {
337+
/// A struct which can be used to peephole certain kinds of finalization
338+
/// that normally happen during l-value emission.
339+
struct ConstantLValue {
340+
llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
341+
bool hasOffsetApplied;
342+
343+
ConstantLValue(std::nullptr_t) : value(nullptr), hasOffsetApplied(false) {}
344+
ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
345+
};
346+
347+
/// A helper class for emitting constant l-values.
348+
class ConstantLValueEmitter
349+
: public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {
350+
CIRGenModule &cgm;
351+
ConstantEmitter &emitter;
352+
const APValue &value;
353+
QualType destType;
354+
355+
// Befriend StmtVisitorBase so that we don't have to expose Visit*.
356+
friend StmtVisitorBase;
357+
358+
public:
359+
ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
360+
QualType destType)
361+
: cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
362+
363+
mlir::Attribute tryEmit();
364+
365+
private:
366+
mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
367+
ConstantLValue tryEmitBase(const APValue::LValueBase &base);
368+
369+
ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }
370+
ConstantLValue VisitConstantExpr(const ConstantExpr *e);
371+
ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);
372+
ConstantLValue VisitStringLiteral(const StringLiteral *e);
373+
ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);
374+
ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);
375+
ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);
376+
ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);
377+
ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);
378+
ConstantLValue VisitCallExpr(const CallExpr *e);
379+
ConstantLValue VisitBlockExpr(const BlockExpr *e);
380+
ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);
381+
ConstantLValue
382+
VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
383+
};
384+
385+
} // namespace
386+
387+
mlir::Attribute ConstantLValueEmitter::tryEmit() {
388+
const APValue::LValueBase &base = value.getLValueBase();
389+
390+
// The destination type should be a pointer or reference
391+
// type, but it might also be a cast thereof.
392+
//
393+
// FIXME: the chain of casts required should be reflected in the APValue.
394+
// We need this in order to correctly handle things like a ptrtoint of a
395+
// non-zero null pointer and addrspace casts that aren't trivially
396+
// represented in LLVM IR.
397+
mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
398+
assert(mlir::isa<cir::PointerType>(destTy));
399+
400+
// If there's no base at all, this is a null or absolute pointer,
401+
// possibly cast back to an integer type.
402+
if (!base)
403+
return tryEmitAbsolute(destTy);
404+
405+
// Otherwise, try to emit the base.
406+
ConstantLValue result = tryEmitBase(base);
407+
408+
// If that failed, we're done.
409+
llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
410+
if (!value)
411+
return {};
412+
413+
// Apply the offset if necessary and not already done.
414+
if (!result.hasOffsetApplied) {
415+
cgm.errorNYI("ConstantLValueEmitter: apply offset");
416+
return {};
417+
}
418+
419+
// Convert to the appropriate type; this could be an lvalue for
420+
// an integer. FIXME: performAddrSpaceCast
421+
if (mlir::isa<cir::PointerType>(destTy)) {
422+
if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))
423+
return attr;
424+
cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");
425+
return {};
426+
}
427+
428+
cgm.errorNYI("ConstantLValueEmitter: other?");
429+
return {};
430+
}
431+
432+
/// Try to emit an absolute l-value, such as a null pointer or an integer
433+
/// bitcast to pointer type.
434+
mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
435+
// If we're producing a pointer, this is easy.
436+
auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
437+
return cgm.getBuilder().getConstPtrAttr(
438+
destPtrTy, value.getLValueOffset().getQuantity());
439+
}
440+
441+
ConstantLValue
442+
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
443+
// Handle values.
444+
if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {
445+
// The constant always points to the canonical declaration. We want to look
446+
// at properties of the most recent declaration at the point of emission.
447+
d = cast<ValueDecl>(d->getMostRecentDecl());
448+
449+
if (d->hasAttr<WeakRefAttr>()) {
450+
cgm.errorNYI(d->getSourceRange(),
451+
"ConstantLValueEmitter: emit pointer base for weakref");
452+
return {};
453+
}
454+
455+
if (auto *fd = dyn_cast<FunctionDecl>(d)) {
456+
cgm.errorNYI(fd->getSourceRange(),
457+
"ConstantLValueEmitter: function decl");
458+
return {};
459+
}
460+
461+
if (auto *vd = dyn_cast<VarDecl>(d)) {
462+
cgm.errorNYI(vd->getSourceRange(), "ConstantLValueEmitter: var decl");
463+
return {};
464+
}
465+
}
466+
467+
// Handle typeid(T).
468+
if (base.dyn_cast<TypeInfoLValue>()) {
469+
cgm.errorNYI("ConstantLValueEmitter: typeid");
470+
return {};
471+
}
472+
473+
// Otherwise, it must be an expression.
474+
return Visit(base.get<const Expr *>());
475+
}
476+
477+
ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {
478+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");
479+
return {};
480+
}
481+
482+
ConstantLValue
483+
ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {
484+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: compound literal");
485+
return {};
486+
}
487+
488+
ConstantLValue
489+
ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {
490+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: string literal");
491+
return {};
492+
}
493+
494+
ConstantLValue
495+
ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {
496+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");
497+
return {};
498+
}
499+
500+
ConstantLValue
501+
ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {
502+
cgm.errorNYI(e->getSourceRange(),
503+
"ConstantLValueEmitter: objc string literal");
504+
return {};
505+
}
506+
507+
ConstantLValue
508+
ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {
509+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");
510+
return {};
511+
}
512+
513+
ConstantLValue
514+
ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
515+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: predefined expr");
516+
return {};
517+
}
518+
519+
ConstantLValue
520+
ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
521+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");
522+
return {};
523+
}
524+
525+
ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
526+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");
527+
return {};
528+
}
529+
530+
ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {
531+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");
532+
return {};
533+
}
534+
535+
ConstantLValue
536+
ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {
537+
cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: cxx typeid expr");
538+
return {};
539+
}
540+
541+
ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
542+
const MaterializeTemporaryExpr *e) {
543+
cgm.errorNYI(e->getSourceRange(),
544+
"ConstantLValueEmitter: materialize temporary expr");
545+
return {};
546+
}
547+
332548
//===----------------------------------------------------------------------===//
333549
// ConstantEmitter
334550
//===----------------------------------------------------------------------===//
@@ -556,23 +772,8 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
556772
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
557773
return {};
558774
}
559-
case APValue::LValue: {
560-
561-
if (value.getLValueBase()) {
562-
cgm.errorNYI("non-null pointer initialization");
563-
} else {
564-
565-
mlir::Type desiredType = cgm.convertType(destType);
566-
if (const cir::PointerType ptrType =
567-
mlir::dyn_cast<cir::PointerType>(desiredType)) {
568-
return builder.getConstPtrAttr(ptrType,
569-
value.getLValueOffset().getQuantity());
570-
} else {
571-
llvm_unreachable("non-pointer variable initialized with a pointer");
572-
}
573-
}
574-
return {};
575-
}
775+
case APValue::LValue:
776+
return ConstantLValueEmitter(*this, value, destType).tryEmit();
576777
case APValue::Struct:
577778
case APValue::Union:
578779
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate struct or union");

0 commit comments

Comments
 (0)