23
23
#include " swift/AST/Pattern.h"
24
24
#include " swift/AST/Types.h"
25
25
#include " swift/Basic/Optional.h"
26
+ #include " ASTVisitor.h"
26
27
#include " GenClass.h"
27
28
#include " GenFunc.h"
28
29
#include " GenInit.h"
32
33
#include " IRGenModule.h"
33
34
#include " Explosion.h"
34
35
#include " LValue.h"
36
+ #include " ScalarTypeInfo.h"
35
37
36
38
using namespace swift ;
37
39
using namespace irgen ;
@@ -122,12 +124,51 @@ void swift::irgen::emitLoadAsInit(IRGenFunction &IGF, const LValue &lvalue,
122
124
return destTI.initializeWithCopy (IGF, dest, baseAddress);
123
125
}
124
126
127
+ namespace {
128
+ // / A visitor for emitting an assignment to a physical object.
129
+ class AssignEmitter : public irgen ::ASTVisitor<AssignEmitter> {
130
+ IRGenFunction &IGF;
131
+ Address Dest;
132
+ const TypeInfo &ObjectTI;
133
+
134
+ public:
135
+ AssignEmitter (IRGenFunction &IGF, Address dest, const TypeInfo &objectTI)
136
+ : IGF(IGF), Dest(dest), ObjectTI(objectTI) {}
137
+
138
+ // / If the expression is a load from something, try to emit that
139
+ // / as an address and then do a copy-assign.
140
+ void visitLoadExpr (LoadExpr *E) {
141
+ if (Optional<Address> src
142
+ = IGF.tryEmitAsAddress (E->getSubExpr (), ObjectTI))
143
+ return ObjectTI.assignWithCopy (IGF, Dest, src.getValue ());
144
+ return visitExpr (E);
145
+ }
146
+
147
+ // / Default case.
148
+ void visitExpr (Expr *E) {
149
+ // TODO: if's natural to emit this r-value into memory, do so
150
+ // and emit a take-assign.
151
+
152
+ Explosion value (ExplosionKind::Maximal);
153
+ IGF.emitRValue (E, value);
154
+ ObjectTI.assign (IGF, value, Dest);
155
+ }
156
+ };
157
+ }
158
+
159
+ // / Emit the given expression for assignment into the given physical object.
160
+ static void emitRValueAsAssign (IRGenFunction &IGF,
161
+ Expr *E, Address object,
162
+ const TypeInfo &objectTI) {
163
+ AssignEmitter (IGF, object, objectTI).visit (E);
164
+ }
165
+
125
166
// / Perform a store into the given path, given the base of the first
126
167
// / component.
127
168
static void emitAssignRecursive (IRGenFunction &IGF,
128
169
Address base,
129
170
const TypeInfo &finalType,
130
- Explosion &finalValue ,
171
+ Expr *finalExpr ,
131
172
LValue::const_iterator pathStart,
132
173
LValue::const_iterator pathEnd) {
133
174
// Drill into any physical components.
@@ -141,7 +182,7 @@ static void emitAssignRecursive(IRGenFunction &IGF,
141
182
142
183
// If we reach the end, do an assignment and we're done.
143
184
if (++pathStart == pathEnd) {
144
- return finalType. assign (IGF, finalValue , base);
185
+ return emitRValueAsAssign (IGF, finalExpr , base, finalType );
145
186
}
146
187
}
147
188
@@ -152,24 +193,24 @@ static void emitAssignRecursive(IRGenFunction &IGF,
152
193
153
194
// If this is the final component, just do a logical store.
154
195
if (pathStart == pathEnd) {
155
- return component.storeExplosion (IGF, finalValue , base, /* preserve*/ false );
196
+ return component.storeRValue (IGF, finalExpr , base, /* preserve*/ false );
156
197
}
157
198
158
199
// Otherwise, load and materialize into a temporary.
159
200
Address temp = component.loadAndMaterialize (IGF, NotOnHeap, base,
160
201
/* preserve*/ true );
161
202
162
203
// Recursively perform the store.
163
- emitAssignRecursive (IGF, temp, finalType, finalValue , pathStart, pathEnd);
204
+ emitAssignRecursive (IGF, temp, finalType, finalExpr , pathStart, pathEnd);
164
205
165
206
// Store the temporary back.
166
207
component.storeMaterialized (IGF, temp, base, /* preserve*/ false );
167
208
}
168
209
169
210
170
- void IRGenFunction::emitAssign (Explosion &rvalue , const LValue &lvalue,
211
+ void IRGenFunction::emitAssign (Expr *E , const LValue &lvalue,
171
212
const TypeInfo &type) {
172
- emitAssignRecursive (*this , Address (), type, rvalue ,
213
+ emitAssignRecursive (*this , Address (), type, E ,
173
214
lvalue.begin (), lvalue.end ());
174
215
}
175
216
@@ -211,21 +252,13 @@ void IRGenFunction::emitLValueAsScalar(const LValue &lvalue, OnHeap_t onHeap,
211
252
}
212
253
}
213
254
214
- void IRGenFunction::emitAssign (Expr *rhs, const LValue &lhs,
215
- const TypeInfo &type) {
216
- // We don't expect that l-value emission is generally going to admit
217
- // maximally-exploded calls.
218
- Explosion explosion (ExplosionKind::Minimal);
219
- emitRValue (rhs, explosion);
220
- emitAssign (explosion, lhs, type);
221
- }
222
-
223
255
namespace {
224
256
// / The type layout for [byref(heap)] types.
225
- class HeapLValueTypeInfo : public TypeInfo {
257
+ class HeapLValueTypeInfo :
258
+ public ScalarTypeInfo<HeapLValueTypeInfo,TypeInfo> {
226
259
public:
227
260
HeapLValueTypeInfo (llvm::StructType *type, Size s, Alignment a)
228
- : TypeInfo (type, s, a, IsNotPOD) {}
261
+ : ScalarTypeInfo (type, s, a, IsNotPOD) {}
229
262
230
263
llvm::StructType *getStorageType () const {
231
264
return cast<llvm::StructType>(TypeInfo::getStorageType ());
@@ -292,10 +325,6 @@ namespace {
292
325
projectOwner (IGF, address));
293
326
}
294
327
295
- void reexplode (IRGenFunction &IGF, Explosion &src, Explosion &dest) const {
296
- src.transferInto (dest, 2 );
297
- }
298
-
299
328
void copy (IRGenFunction &IGF, Explosion &src, Explosion &dest) const {
300
329
src.transferInto (dest, 1 );
301
330
IGF.emitRetain (src.claimNext ().getValue (), dest);
@@ -563,12 +592,16 @@ namespace {
563
592
emitVoidCall (IGF, setter, args);
564
593
}
565
594
566
- void storeExplosion (IRGenFunction &IGF, Explosion &raw ,
567
- Address base, bool preserve) const {
568
- Callee setter = Target.getSetter (IGF, raw. getKind () );
595
+ void storeRValue (IRGenFunction &IGF, Expr *rvalue ,
596
+ Address base, bool preserve) const {
597
+ Callee setter = Target.getSetter (IGF, ExplosionKind::Maximal );
569
598
599
+ // Emit the r-value at the natural level of the setter we found.
600
+ Explosion value (setter.getExplosionLevel ());
601
+ IGF.emitRValue (rvalue, value);
602
+
570
603
const TypeInfo &valueTI = IGF.getFragileTypeInfo (Target.getType ());
571
- store (IGF, setter, base, raw , valueTI, preserve);
604
+ store (IGF, setter, base, value , valueTI, preserve);
572
605
}
573
606
574
607
void storeMaterialized (IRGenFunction &IGF, Address temp,
@@ -702,6 +735,17 @@ LValue swift::irgen::emitMemberRefLValue(IRGenFunction &IGF, MemberRefExpr *E) {
702
735
return lvalue;
703
736
}
704
737
738
+ // / Try to emit the given member-reference as an address.
739
+ Optional<Address> irgen::tryEmitMemberRefAsAddress (IRGenFunction &IGF,
740
+ MemberRefExpr *E) {
741
+ // Can't do anything if the member reference is logical.
742
+ if (isVarAccessLogical (IGF, E->getDecl ()))
743
+ return Nothing;
744
+
745
+ // FIXME: actually implement this.
746
+ return Nothing;
747
+ }
748
+
705
749
// / Emit a reference to a global variable.
706
750
LValue IRGenFunction::getGlobal (VarDecl *var) {
707
751
// If we need to access this variable logically, use a
0 commit comments