@@ -461,7 +461,8 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
461461
462462 llvm::StringRef fieldName = field->getName ();
463463 unsigned fieldIndex;
464- assert (!cir::MissingFeatures::lambdaFieldToName ());
464+ if (cgm.lambdaFieldToName .count (field))
465+ fieldName = cgm.lambdaFieldToName [field];
465466
466467 if (rec->isUnion ())
467468 fieldIndex = field->getFieldIndex ();
@@ -476,8 +477,16 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
476477
477478 // If this is a reference field, load the reference right now.
478479 if (fieldType->isReferenceType ()) {
479- cgm.errorNYI (field->getSourceRange (), " emitLValueForField: reference type" );
480- return LValue ();
480+ assert (!cir::MissingFeatures::opTBAA ());
481+ LValue refLVal = makeAddrLValue (addr, fieldType, fieldBaseInfo);
482+ if (recordCVR & Qualifiers::Volatile)
483+ refLVal.getQuals ().addVolatile ();
484+ addr = emitLoadOfReference (refLVal, getLoc (field->getSourceRange ()),
485+ &fieldBaseInfo);
486+
487+ // Qualifiers on the struct don't apply to the referencee.
488+ recordCVR = 0 ;
489+ fieldType = fieldType->getPointeeType ();
481490 }
482491
483492 if (field->hasAttr <AnnotateAttr>()) {
@@ -619,6 +628,38 @@ static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
619628 return cgm.getAddrOfFunction (gd);
620629}
621630
631+ static LValue emitCapturedFieldLValue (CIRGenFunction &cgf, const FieldDecl *fd,
632+ mlir::Value thisValue) {
633+ return cgf.emitLValueForLambdaField (fd, thisValue);
634+ }
635+
636+ // / Given that we are currently emitting a lambda, emit an l-value for
637+ // / one of its members.
638+ // /
639+ LValue CIRGenFunction::emitLValueForLambdaField (const FieldDecl *field,
640+ mlir::Value thisValue) {
641+ bool hasExplicitObjectParameter = false ;
642+ const auto *methD = dyn_cast_if_present<CXXMethodDecl>(curCodeDecl);
643+ LValue lambdaLV;
644+ if (methD) {
645+ hasExplicitObjectParameter = methD->isExplicitObjectMemberFunction ();
646+ assert (methD->getParent ()->isLambda ());
647+ assert (methD->getParent () == field->getParent ());
648+ }
649+ if (hasExplicitObjectParameter) {
650+ cgm.errorNYI (field->getSourceRange (), " ExplicitObjectMemberFunction" );
651+ } else {
652+ QualType lambdaTagType =
653+ getContext ().getCanonicalTagType (field->getParent ());
654+ lambdaLV = makeNaturalAlignAddrLValue (thisValue, lambdaTagType);
655+ }
656+ return emitLValueForField (lambdaLV, field);
657+ }
658+
659+ LValue CIRGenFunction::emitLValueForLambdaField (const FieldDecl *field) {
660+ return emitLValueForLambdaField (field, cxxabiThisValue);
661+ }
662+
622663static LValue emitFunctionDeclLValue (CIRGenFunction &cgf, const Expr *e,
623664 GlobalDecl gd) {
624665 const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl ());
@@ -645,13 +686,90 @@ static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e,
645686 AlignmentSource::Decl);
646687}
647688
689+ // / Determine whether we can emit a reference to \p vd from the current
690+ // / context, despite not necessarily having seen an odr-use of the variable in
691+ // / this context.
692+ // / TODO(cir): This could be shared with classic codegen.
693+ static bool canEmitSpuriousReferenceToVariable (CIRGenFunction &cgf,
694+ const DeclRefExpr *e,
695+ const VarDecl *vd) {
696+ // For a variable declared in an enclosing scope, do not emit a spurious
697+ // reference even if we have a capture, as that will emit an unwarranted
698+ // reference to our capture state, and will likely generate worse code than
699+ // emitting a local copy.
700+ if (e->refersToEnclosingVariableOrCapture ())
701+ return false ;
702+
703+ // For a local declaration declared in this function, we can always reference
704+ // it even if we don't have an odr-use.
705+ if (vd->hasLocalStorage ()) {
706+ return vd->getDeclContext () ==
707+ dyn_cast_or_null<DeclContext>(cgf.curCodeDecl );
708+ }
709+
710+ // For a global declaration, we can emit a reference to it if we know
711+ // for sure that we are able to emit a definition of it.
712+ vd = vd->getDefinition (cgf.getContext ());
713+ if (!vd)
714+ return false ;
715+
716+ // Don't emit a spurious reference if it might be to a variable that only
717+ // exists on a different device / target.
718+ // FIXME: This is unnecessarily broad. Check whether this would actually be a
719+ // cross-target reference.
720+ if (cgf.getLangOpts ().OpenMP || cgf.getLangOpts ().CUDA ||
721+ cgf.getLangOpts ().OpenCL ) {
722+ return false ;
723+ }
724+
725+ // We can emit a spurious reference only if the linkage implies that we'll
726+ // be emitting a non-interposable symbol that will be retained until link
727+ // time.
728+ switch (cgf.cgm .getCIRLinkageVarDefinition (vd, /* IsConstant=*/ false )) {
729+ case cir::GlobalLinkageKind::ExternalLinkage:
730+ case cir::GlobalLinkageKind::LinkOnceODRLinkage:
731+ case cir::GlobalLinkageKind::WeakODRLinkage:
732+ case cir::GlobalLinkageKind::InternalLinkage:
733+ case cir::GlobalLinkageKind::PrivateLinkage:
734+ return true ;
735+ default :
736+ return false ;
737+ }
738+ }
739+
648740LValue CIRGenFunction::emitDeclRefLValue (const DeclRefExpr *e) {
649741 const NamedDecl *nd = e->getDecl ();
650742 QualType ty = e->getType ();
651743
652744 assert (e->isNonOdrUse () != NOUR_Unevaluated &&
653745 " should not emit an unevaluated operand" );
654746
747+ if (const auto *vd = dyn_cast<VarDecl>(nd)) {
748+ // Global Named registers access via intrinsics only
749+ if (vd->getStorageClass () == SC_Register && vd->hasAttr <AsmLabelAttr>() &&
750+ !vd->isLocalVarDecl ()) {
751+ cgm.errorNYI (e->getSourceRange (),
752+ " emitDeclRefLValue: Global Named registers access" );
753+ return LValue ();
754+ }
755+
756+ if (e->isNonOdrUse () == NOUR_Constant &&
757+ (vd->getType ()->isReferenceType () ||
758+ !canEmitSpuriousReferenceToVariable (*this , e, vd))) {
759+ cgm.errorNYI (e->getSourceRange (), " emitDeclRefLValue: NonOdrUse" );
760+ return LValue ();
761+ }
762+
763+ // Check for captured variables.
764+ if (e->refersToEnclosingVariableOrCapture ()) {
765+ vd = vd->getCanonicalDecl ();
766+ if (FieldDecl *fd = lambdaCaptureFields.lookup (vd))
767+ return emitCapturedFieldLValue (*this , fd, cxxabiThisValue);
768+ assert (!cir::MissingFeatures::cgCapturedStmtInfo ());
769+ assert (!cir::MissingFeatures::openMP ());
770+ }
771+ }
772+
655773 if (const auto *vd = dyn_cast<VarDecl>(nd)) {
656774 // Checks for omitted feature handling
657775 assert (!cir::MissingFeatures::opAllocaStaticLocal ());
0 commit comments