@@ -461,7 +461,8 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
461
461
462
462
llvm::StringRef fieldName = field->getName ();
463
463
unsigned fieldIndex;
464
- assert (!cir::MissingFeatures::lambdaFieldToName ());
464
+ if (cgm.lambdaFieldToName .count (field))
465
+ fieldName = cgm.lambdaFieldToName [field];
465
466
466
467
if (rec->isUnion ())
467
468
fieldIndex = field->getFieldIndex ();
@@ -476,8 +477,16 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
476
477
477
478
// If this is a reference field, load the reference right now.
478
479
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 ();
481
490
}
482
491
483
492
if (field->hasAttr <AnnotateAttr>()) {
@@ -619,6 +628,38 @@ static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
619
628
return cgm.getAddrOfFunction (gd);
620
629
}
621
630
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
+
622
663
static LValue emitFunctionDeclLValue (CIRGenFunction &cgf, const Expr *e,
623
664
GlobalDecl gd) {
624
665
const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl ());
@@ -645,13 +686,90 @@ static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e,
645
686
AlignmentSource::Decl);
646
687
}
647
688
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
+
648
740
LValue CIRGenFunction::emitDeclRefLValue (const DeclRefExpr *e) {
649
741
const NamedDecl *nd = e->getDecl ();
650
742
QualType ty = e->getType ();
651
743
652
744
assert (e->isNonOdrUse () != NOUR_Unevaluated &&
653
745
" should not emit an unevaluated operand" );
654
746
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
+
655
773
if (const auto *vd = dyn_cast<VarDecl>(nd)) {
656
774
// Checks for omitted feature handling
657
775
assert (!cir::MissingFeatures::opAllocaStaticLocal ());
0 commit comments