@@ -24,6 +24,73 @@ using namespace clang;
2424using namespace clang ::CIRGen;
2525
2626namespace {
27+ // FIXME(cir): This should be a common helper between CIRGen
28+ // and traditional CodeGen
29+ // / Is the value of the given expression possibly a reference to or
30+ // / into a __block variable?
31+ static bool isBlockVarRef (const Expr *e) {
32+ // Make sure we look through parens.
33+ e = e->IgnoreParens ();
34+
35+ // Check for a direct reference to a __block variable.
36+ if (const DeclRefExpr *dre = dyn_cast<DeclRefExpr>(e)) {
37+ const VarDecl *var = dyn_cast<VarDecl>(dre->getDecl ());
38+ return (var && var->hasAttr <BlocksAttr>());
39+ }
40+
41+ // More complicated stuff.
42+
43+ // Binary operators.
44+ if (const BinaryOperator *op = dyn_cast<BinaryOperator>(e)) {
45+ // For an assignment or pointer-to-member operation, just care
46+ // about the LHS.
47+ if (op->isAssignmentOp () || op->isPtrMemOp ())
48+ return isBlockVarRef (op->getLHS ());
49+
50+ // For a comma, just care about the RHS.
51+ if (op->getOpcode () == BO_Comma)
52+ return isBlockVarRef (op->getRHS ());
53+
54+ // FIXME: pointer arithmetic?
55+ return false ;
56+
57+ // Check both sides of a conditional operator.
58+ } else if (const AbstractConditionalOperator *op =
59+ dyn_cast<AbstractConditionalOperator>(e)) {
60+ return isBlockVarRef (op->getTrueExpr ()) ||
61+ isBlockVarRef (op->getFalseExpr ());
62+
63+ // OVEs are required to support BinaryConditionalOperators.
64+ } else if (const OpaqueValueExpr *op = dyn_cast<OpaqueValueExpr>(e)) {
65+ if (const Expr *src = op->getSourceExpr ())
66+ return isBlockVarRef (src);
67+
68+ // Casts are necessary to get things like (*(int*)&var) = foo().
69+ // We don't really care about the kind of cast here, except
70+ // we don't want to look through l2r casts, because it's okay
71+ // to get the *value* in a __block variable.
72+ } else if (const CastExpr *cast = dyn_cast<CastExpr>(e)) {
73+ if (cast->getCastKind () == CK_LValueToRValue)
74+ return false ;
75+ return isBlockVarRef (cast->getSubExpr ());
76+
77+ // Handle unary operators. Again, just aggressively look through
78+ // it, ignoring the operation.
79+ } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
80+ return isBlockVarRef (uop->getSubExpr ());
81+
82+ // Look into the base of a field access.
83+ } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
84+ return isBlockVarRef (mem->getBase ());
85+
86+ // Look into the base of a subscript.
87+ } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(e)) {
88+ return isBlockVarRef (sub->getBase ());
89+ }
90+
91+ return false ;
92+ }
93+
2794class AggExprEmitter : public StmtVisitor <AggExprEmitter> {
2895
2996 CIRGenFunction &cgf;
@@ -41,9 +108,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
41108 AggValueSlot ensureSlot (mlir::Location loc, QualType t) {
42109 if (!dest.isIgnored ())
43110 return dest;
44-
45- cgf.cgm .errorNYI (loc, " Slot for ignored address" );
46- return dest;
111+ return cgf.createAggTemp (t, loc, " agg.tmp.ensured" );
47112 }
48113
49114 void ensureDest (mlir::Location loc, QualType ty) {
@@ -89,6 +154,47 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
89154 (void )cgf.emitCompoundStmt (*e->getSubStmt (), &retAlloca, dest);
90155 }
91156
157+ void VisitBinAssign (const BinaryOperator *e) {
158+ // For an assignment to work, the value on the right has
159+ // to be compatible with the value on the left.
160+ assert (cgf.getContext ().hasSameUnqualifiedType (e->getLHS ()->getType (),
161+ e->getRHS ()->getType ()) &&
162+ " Invalid assignment" );
163+
164+ if (isBlockVarRef (e->getLHS ()) &&
165+ e->getRHS ()->HasSideEffects (cgf.getContext ())) {
166+ cgf.cgm .errorNYI (e->getSourceRange (),
167+ " block var reference with side effects" );
168+ return ;
169+ }
170+
171+ LValue lhs = cgf.emitLValue (e->getLHS ());
172+
173+ // If we have an atomic type, evaluate into the destination and then
174+ // do an atomic copy.
175+ assert (!cir::MissingFeatures::atomicTypes ());
176+
177+ // Codegen the RHS so that it stores directly into the LHS.
178+ assert (!cir::MissingFeatures::aggValueSlotGC ());
179+ AggValueSlot lhsSlot = AggValueSlot::forLValue (
180+ lhs, AggValueSlot::IsDestructed, AggValueSlot::IsAliased,
181+ AggValueSlot::MayOverlap);
182+
183+ // A non-volatile aggregate destination might have volatile member.
184+ if (!lhsSlot.isVolatile () && cgf.hasVolatileMember (e->getLHS ()->getType ()))
185+ lhsSlot.setVolatile (true );
186+
187+ cgf.emitAggExpr (e->getRHS (), lhsSlot);
188+
189+ // Copy into the destination if the assignment isn't ignored.
190+ emitFinalDestCopy (e->getType (), lhs);
191+
192+ if (!dest.isIgnored () && !dest.isExternallyDestructed () &&
193+ e->getType ().isDestructedType () == QualType::DK_nontrivial_c_struct)
194+ cgf.pushDestroy (QualType::DK_nontrivial_c_struct, dest.getAddress (),
195+ e->getType ());
196+ }
197+
92198 void VisitDeclRefExpr (DeclRefExpr *e) { emitAggLoadOfLValue (e); }
93199
94200 void VisitInitListExpr (InitListExpr *e);
@@ -195,9 +301,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
195301 cgf.cgm .errorNYI (e->getSourceRange (),
196302 " AggExprEmitter: VisitPointerToDataMemberBinaryOperator" );
197303 }
198- void VisitBinAssign (const BinaryOperator *e) {
199- cgf.cgm .errorNYI (e->getSourceRange (), " AggExprEmitter: VisitBinAssign" );
200- }
201304 void VisitBinComma (const BinaryOperator *e) {
202305 cgf.emitIgnoredExpr (e->getLHS ());
203306 Visit (e->getRHS ());
@@ -487,7 +590,8 @@ void AggExprEmitter::emitCopy(QualType type, const AggValueSlot &dest,
487590 LValue destLV = cgf.makeAddrLValue (dest.getAddress (), type);
488591 LValue srcLV = cgf.makeAddrLValue (src.getAddress (), type);
489592 assert (!cir::MissingFeatures::aggValueSlotVolatile ());
490- cgf.emitAggregateCopy (destLV, srcLV, type, dest.mayOverlap ());
593+ cgf.emitAggregateCopy (destLV, srcLV, type, dest.mayOverlap (),
594+ dest.isVolatile () || src.isVolatile ());
491595}
492596
493597void AggExprEmitter::emitInitializationToLValue (Expr *e, LValue lv) {
@@ -788,7 +892,8 @@ void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
788892}
789893
790894void CIRGenFunction::emitAggregateCopy (LValue dest, LValue src, QualType ty,
791- AggValueSlot::Overlap_t mayOverlap) {
895+ AggValueSlot::Overlap_t mayOverlap,
896+ bool isVolatile) {
792897 // TODO(cir): this function needs improvements, commented code for now since
793898 // this will be touched again soon.
794899 assert (!ty->isAnyComplexType () && " Unexpected copy of complex" );
@@ -844,7 +949,7 @@ void CIRGenFunction::emitAggregateCopy(LValue dest, LValue src, QualType ty,
844949 cgm.errorNYI (" emitAggregateCopy: GC" );
845950
846951 [[maybe_unused]] cir::CopyOp copyOp =
847- builder.createCopy (destPtr.getPointer (), srcPtr.getPointer ());
952+ builder.createCopy (destPtr.getPointer (), srcPtr.getPointer (), isVolatile );
848953
849954 assert (!cir::MissingFeatures::opTBAA ());
850955}
0 commit comments