@@ -29,6 +29,75 @@ using namespace cir;
2929using namespace clang ;
3030
3131namespace {
32+
33+ // FIXME(cir): This should be a common helper between CIRGen
34+ // and traditional CodeGen
35+ // / Is the value of the given expression possibly a reference to or
36+ // / into a __block variable?
37+ static bool isBlockVarRef (const Expr *E) {
38+ // Make sure we look through parens.
39+ E = E->IgnoreParens ();
40+
41+ // Check for a direct reference to a __block variable.
42+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
43+ const VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl ());
44+ return (var && var->hasAttr <BlocksAttr>());
45+ }
46+
47+ // More complicated stuff.
48+
49+ // Binary operators.
50+ if (const BinaryOperator *op = dyn_cast<BinaryOperator>(E)) {
51+ // For an assignment or pointer-to-member operation, just care
52+ // about the LHS.
53+ if (op->isAssignmentOp () || op->isPtrMemOp ())
54+ return isBlockVarRef (op->getLHS ());
55+
56+ // For a comma, just care about the RHS.
57+ if (op->getOpcode () == BO_Comma)
58+ return isBlockVarRef (op->getRHS ());
59+
60+ // FIXME: pointer arithmetic?
61+ return false ;
62+
63+ // Check both sides of a conditional operator.
64+ } else if (const AbstractConditionalOperator *op
65+ = dyn_cast<AbstractConditionalOperator>(E)) {
66+ return isBlockVarRef (op->getTrueExpr ())
67+ || isBlockVarRef (op->getFalseExpr ());
68+
69+ // OVEs are required to support BinaryConditionalOperators.
70+ } else if (const OpaqueValueExpr *op
71+ = dyn_cast<OpaqueValueExpr>(E)) {
72+ if (const Expr *src = op->getSourceExpr ())
73+ return isBlockVarRef (src);
74+
75+ // Casts are necessary to get things like (*(int*)&var) = foo().
76+ // We don't really care about the kind of cast here, except
77+ // we don't want to look through l2r casts, because it's okay
78+ // to get the *value* in a __block variable.
79+ } else if (const CastExpr *cast = dyn_cast<CastExpr>(E)) {
80+ if (cast->getCastKind () == CK_LValueToRValue)
81+ return false ;
82+ return isBlockVarRef (cast->getSubExpr ());
83+
84+ // Handle unary operators. Again, just aggressively look through
85+ // it, ignoring the operation.
86+ } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E)) {
87+ return isBlockVarRef (uop->getSubExpr ());
88+
89+ // Look into the base of a field access.
90+ } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(E)) {
91+ return isBlockVarRef (mem->getBase ());
92+
93+ // Look into the base of a subscript.
94+ } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(E)) {
95+ return isBlockVarRef (sub->getBase ());
96+ }
97+
98+ return false ;
99+ }
100+
32101class AggExprEmitter : public StmtVisitor <AggExprEmitter> {
33102 CIRGenFunction &CGF;
34103 AggValueSlot Dest;
@@ -117,8 +186,8 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
117186
118187 // l-values
119188 void VisitDeclRefExpr (DeclRefExpr *E) { buildAggLoadOfLValue (E); }
120- void VisitMemberExpr (MemberExpr *E) { llvm_unreachable ( " NYI " ); }
121- void VisitUnaryDeref (UnaryOperator *E) { llvm_unreachable ( " NYI " ); }
189+ void VisitMemberExpr (MemberExpr *E) { buildAggLoadOfLValue (E ); }
190+ void VisitUnaryDeref (UnaryOperator *E) { buildAggLoadOfLValue (E ); }
122191 void VisitStringLiteral (StringLiteral *E) { llvm_unreachable (" NYI" ); }
123192 void VisitCompoundLIteralExpr (CompoundLiteralExpr *E) {
124193 llvm_unreachable (" NYI" );
@@ -136,7 +205,50 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
136205 void VisitPointerToDataMemberBinaryOperator (const BinaryOperator *E) {
137206 llvm_unreachable (" NYI" );
138207 }
139- void VisitBinAssign (const BinaryOperator *E) { llvm_unreachable (" NYI" ); }
208+ void VisitBinAssign (const BinaryOperator *E) {
209+
210+ // For an assignment to work, the value on the right has
211+ // to be compatible with the value on the left.
212+ assert (CGF.getContext ().hasSameUnqualifiedType (E->getLHS ()->getType (),
213+ E->getRHS ()->getType ())
214+ && " Invalid assignment" );
215+
216+ if (isBlockVarRef (E->getLHS ()) &&
217+ E->getRHS ()->HasSideEffects (CGF.getContext ())) {
218+ llvm_unreachable (" NYI" );
219+ }
220+
221+ LValue lhs = CGF.buildLValue (E->getLHS ());
222+
223+ // If we have an atomic type, evaluate into the destination and then
224+ // do an atomic copy.
225+ if (lhs.getType ()->isAtomicType () ||
226+ CGF.LValueIsSuitableForInlineAtomic (lhs)) {
227+ assert (!UnimplementedFeature::atomicTypes ());
228+ return ;
229+ }
230+
231+ // Codegen the RHS so that it stores directly into the LHS.
232+ AggValueSlot lhsSlot = AggValueSlot::forLValue (
233+ lhs, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers,
234+ AggValueSlot::IsAliased, AggValueSlot::MayOverlap);
235+
236+ // A non-volatile aggregate destination might have volatile member.
237+ if (!lhsSlot.isVolatile () &&
238+ CGF.hasVolatileMember (E->getLHS ()->getType ()))
239+ assert (!UnimplementedFeature::atomicTypes ());
240+
241+ CGF.buildAggExpr (E->getRHS (), lhsSlot);
242+
243+ // Copy into the destination if the assignment isn't ignored.
244+ buildFinalDestCopy (E->getType (), lhs);
245+
246+ if (!Dest.isIgnored () && !Dest.isExternallyDestructed () &&
247+ E->getType ().isDestructedType () == QualType::DK_nontrivial_c_struct)
248+ CGF.pushDestroy (QualType::DK_nontrivial_c_struct, Dest.getAddress (),
249+ E->getType ());
250+ }
251+
140252 void VisitBinComma (const BinaryOperator *E) { llvm_unreachable (" NYI" ); }
141253 void VisitBinCmp (const BinaryOperator *E) { llvm_unreachable (" NYI" ); }
142254 void VisitCXXRewrittenBinaryOperator (CXXRewrittenBinaryOperator *E) {
0 commit comments