@@ -29,6 +29,75 @@ using namespace cir;
29
29
using namespace clang ;
30
30
31
31
namespace {
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
+
32
101
class AggExprEmitter : public StmtVisitor <AggExprEmitter> {
33
102
CIRGenFunction &CGF;
34
103
AggValueSlot Dest;
@@ -117,8 +186,8 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
117
186
118
187
// l-values
119
188
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 ); }
122
191
void VisitStringLiteral (StringLiteral *E) { llvm_unreachable (" NYI" ); }
123
192
void VisitCompoundLIteralExpr (CompoundLiteralExpr *E) {
124
193
llvm_unreachable (" NYI" );
@@ -136,7 +205,50 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
136
205
void VisitPointerToDataMemberBinaryOperator (const BinaryOperator *E) {
137
206
llvm_unreachable (" NYI" );
138
207
}
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
+
140
252
void VisitBinComma (const BinaryOperator *E) { llvm_unreachable (" NYI" ); }
141
253
void VisitBinCmp (const BinaryOperator *E) { llvm_unreachable (" NYI" ); }
142
254
void VisitCXXRewrittenBinaryOperator (CXXRewrittenBinaryOperator *E) {
0 commit comments