Skip to content

Commit 72ebeee

Browse files
committed
Try to optimize assignment a bit more, and fix assignment
of protocol types to correctly handle self-assignment. This ends up creating such a large amount of code that it's worth extracting into its own helper function. Fortunately, this can be the same helper function for every protocol type. Swift SVN r1905
1 parent 06992ee commit 72ebeee

12 files changed

+278
-54
lines changed

lib/IRGen/GenArray.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ namespace {
5858
// FIXME
5959
}
6060

61+
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src) const {
62+
// FIXME
63+
}
64+
65+
void assignWithTake(IRGenFunction &IGF, Address dest, Address src) const {
66+
// FIXME
67+
}
68+
6169
void initialize(IRGenFunction &IGF, Explosion &explosion, Address addr) const {
6270
// FIXME
6371
}

lib/IRGen/GenExpr.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,7 @@ namespace {
500500
}
501501

502502
Optional<Address> visitMemberRefExpr(MemberRefExpr *E) {
503-
IGF.unimplemented(E->getLoc(), "emit address of MemberRefExpr");
504-
return Optional<Address>();
503+
return tryEmitMemberRefAsAddress(IGF, E);
505504
}
506505

507506
// These expressions aren't naturally already in memory.

lib/IRGen/GenLValue.cpp

+69-25
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Pattern.h"
2424
#include "swift/AST/Types.h"
2525
#include "swift/Basic/Optional.h"
26+
#include "ASTVisitor.h"
2627
#include "GenClass.h"
2728
#include "GenFunc.h"
2829
#include "GenInit.h"
@@ -32,6 +33,7 @@
3233
#include "IRGenModule.h"
3334
#include "Explosion.h"
3435
#include "LValue.h"
36+
#include "ScalarTypeInfo.h"
3537

3638
using namespace swift;
3739
using namespace irgen;
@@ -122,12 +124,51 @@ void swift::irgen::emitLoadAsInit(IRGenFunction &IGF, const LValue &lvalue,
122124
return destTI.initializeWithCopy(IGF, dest, baseAddress);
123125
}
124126

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+
125166
/// Perform a store into the given path, given the base of the first
126167
/// component.
127168
static void emitAssignRecursive(IRGenFunction &IGF,
128169
Address base,
129170
const TypeInfo &finalType,
130-
Explosion &finalValue,
171+
Expr *finalExpr,
131172
LValue::const_iterator pathStart,
132173
LValue::const_iterator pathEnd) {
133174
// Drill into any physical components.
@@ -141,7 +182,7 @@ static void emitAssignRecursive(IRGenFunction &IGF,
141182

142183
// If we reach the end, do an assignment and we're done.
143184
if (++pathStart == pathEnd) {
144-
return finalType.assign(IGF, finalValue, base);
185+
return emitRValueAsAssign(IGF, finalExpr, base, finalType);
145186
}
146187
}
147188

@@ -152,24 +193,24 @@ static void emitAssignRecursive(IRGenFunction &IGF,
152193

153194
// If this is the final component, just do a logical store.
154195
if (pathStart == pathEnd) {
155-
return component.storeExplosion(IGF, finalValue, base, /*preserve*/ false);
196+
return component.storeRValue(IGF, finalExpr, base, /*preserve*/ false);
156197
}
157198

158199
// Otherwise, load and materialize into a temporary.
159200
Address temp = component.loadAndMaterialize(IGF, NotOnHeap, base,
160201
/*preserve*/ true);
161202

162203
// Recursively perform the store.
163-
emitAssignRecursive(IGF, temp, finalType, finalValue, pathStart, pathEnd);
204+
emitAssignRecursive(IGF, temp, finalType, finalExpr, pathStart, pathEnd);
164205

165206
// Store the temporary back.
166207
component.storeMaterialized(IGF, temp, base, /*preserve*/ false);
167208
}
168209

169210

170-
void IRGenFunction::emitAssign(Explosion &rvalue, const LValue &lvalue,
211+
void IRGenFunction::emitAssign(Expr *E, const LValue &lvalue,
171212
const TypeInfo &type) {
172-
emitAssignRecursive(*this, Address(), type, rvalue,
213+
emitAssignRecursive(*this, Address(), type, E,
173214
lvalue.begin(), lvalue.end());
174215
}
175216

@@ -211,21 +252,13 @@ void IRGenFunction::emitLValueAsScalar(const LValue &lvalue, OnHeap_t onHeap,
211252
}
212253
}
213254

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-
223255
namespace {
224256
/// The type layout for [byref(heap)] types.
225-
class HeapLValueTypeInfo : public TypeInfo {
257+
class HeapLValueTypeInfo :
258+
public ScalarTypeInfo<HeapLValueTypeInfo,TypeInfo> {
226259
public:
227260
HeapLValueTypeInfo(llvm::StructType *type, Size s, Alignment a)
228-
: TypeInfo(type, s, a, IsNotPOD) {}
261+
: ScalarTypeInfo(type, s, a, IsNotPOD) {}
229262

230263
llvm::StructType *getStorageType() const {
231264
return cast<llvm::StructType>(TypeInfo::getStorageType());
@@ -292,10 +325,6 @@ namespace {
292325
projectOwner(IGF, address));
293326
}
294327

295-
void reexplode(IRGenFunction &IGF, Explosion &src, Explosion &dest) const {
296-
src.transferInto(dest, 2);
297-
}
298-
299328
void copy(IRGenFunction &IGF, Explosion &src, Explosion &dest) const {
300329
src.transferInto(dest, 1);
301330
IGF.emitRetain(src.claimNext().getValue(), dest);
@@ -563,12 +592,16 @@ namespace {
563592
emitVoidCall(IGF, setter, args);
564593
}
565594

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);
569598

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+
570603
const TypeInfo &valueTI = IGF.getFragileTypeInfo(Target.getType());
571-
store(IGF, setter, base, raw, valueTI, preserve);
604+
store(IGF, setter, base, value, valueTI, preserve);
572605
}
573606

574607
void storeMaterialized(IRGenFunction &IGF, Address temp,
@@ -702,6 +735,17 @@ LValue swift::irgen::emitMemberRefLValue(IRGenFunction &IGF, MemberRefExpr *E) {
702735
return lvalue;
703736
}
704737

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+
705749
/// Emit a reference to a global variable.
706750
LValue IRGenFunction::getGlobal(VarDecl *var) {
707751
// If we need to access this variable logically, use a

lib/IRGen/GenLValue.h

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace swift {
2121
class MemberRefExpr;
2222
class RequalifyExpr;
2323
class SubscriptExpr;
24+
template <class T> class Optional;
2425

2526
namespace irgen {
2627
class Address;
@@ -42,6 +43,10 @@ namespace irgen {
4243
/// Emit an l-value for a subscripting.
4344
LValue emitSubscriptLValue(IRGenFunction &IGF, SubscriptExpr *E);
4445

46+
/// Try to emit a member reference as an address.
47+
Optional<Address> tryEmitMemberRefAsAddress(IRGenFunction &IGF,
48+
MemberRefExpr *E);
49+
4550
} // end namespace irgen
4651
} // end namespace swift
4752

lib/IRGen/GenMeta.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,24 @@
2121
#include "llvm/DerivedTypes.h"
2222

2323
#include "Address.h"
24-
#include "GenType.h"
2524
#include "IRGenModule.h"
25+
#include "ScalarTypeInfo.h"
2626

2727
#include "GenMeta.h"
2828

2929
using namespace swift;
3030
using namespace irgen;
3131

3232
namespace {
33-
struct EmptyTypeInfo : TypeInfo {
33+
struct EmptyTypeInfo : ScalarTypeInfo<EmptyTypeInfo, TypeInfo> {
3434
EmptyTypeInfo(llvm::Type *ty)
35-
: TypeInfo(ty, Size(0), Alignment(1), IsPOD) {}
35+
: ScalarTypeInfo(ty, Size(0), Alignment(1), IsPOD) {}
3636
unsigned getExplosionSize(ExplosionKind kind) const { return 0; }
3737
void getSchema(ExplosionSchema &schema) const {}
3838
void load(IRGenFunction &IGF, Address addr, Explosion &e) const {}
3939
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {}
4040
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {}
4141
void initialize(IRGenFunction &IGF, Explosion &e, Address addr) const {}
42-
void reexplode(IRGenFunction &IGF, Explosion &src, Explosion &dest) const {}
4342
void copy(IRGenFunction &IGF, Explosion &src, Explosion &dest) const {}
4443
void manage(IRGenFunction &IGF, Explosion &src, Explosion &dest) const {}
4544
void destroy(IRGenFunction &IGF, Address addr) const {}

lib/IRGen/GenOneOf.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ namespace {
102102
// FIXME
103103
}
104104

105+
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src) const {
106+
// FIXME
107+
}
108+
109+
void assignWithTake(IRGenFunction &IGF, Address dest, Address src) const {
110+
// FIXME
111+
}
112+
105113
void initialize(IRGenFunction &IGF, Explosion &e, Address addr) const {
106114
// FIXME
107115
}
@@ -173,6 +181,20 @@ namespace {
173181
Singleton->assign(IGF, e, getSingletonAddress(IGF, addr));
174182
}
175183

184+
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src) const {
185+
if (!Singleton) return;
186+
dest = getSingletonAddress(IGF, dest);
187+
src = getSingletonAddress(IGF, src);
188+
Singleton->assignWithCopy(IGF, dest, src);
189+
}
190+
191+
void assignWithTake(IRGenFunction &IGF, Address dest, Address src) const {
192+
if (!Singleton) return;
193+
dest = getSingletonAddress(IGF, dest);
194+
src = getSingletonAddress(IGF, src);
195+
Singleton->assignWithTake(IGF, dest, src);
196+
}
197+
176198
void initialize(IRGenFunction &IGF, Explosion &e, Address addr) const {
177199
if (!Singleton) return;
178200
Singleton->initialize(IGF, e, getSingletonAddress(IGF, addr));

0 commit comments

Comments
 (0)