mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Fix a bug with returning value that need to be refcounted:
we want to do a take-load out of the return address slot instead of a normal load, or else we'll end up +1'ing an already +1 value. Swift SVN r1564
This commit is contained in:
@@ -44,6 +44,10 @@ namespace {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &explosion, Address addr) const {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
@@ -310,6 +310,16 @@ namespace {
|
||||
IGF.emitLoadAndRetain(dataAddr, e);
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
// Load the function.
|
||||
Address fnAddr = projectFunction(IGF, addr);
|
||||
e.addUnmanaged(IGF.Builder.CreateLoad(fnAddr));
|
||||
|
||||
// Load the data.
|
||||
Address dataAddr = projectData(IGF, addr);
|
||||
e.addUnmanaged(IGF.Builder.CreateLoad(dataAddr));
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address address) const {
|
||||
// Store the function pointer.
|
||||
Address fnAddr = projectFunction(IGF, address);
|
||||
@@ -1439,7 +1449,7 @@ void IRGenFunction::emitEpilogue() {
|
||||
Builder.CreateRetVoid();
|
||||
} else {
|
||||
Explosion result(CurExplosionLevel);
|
||||
resultType.load(*this, ReturnSlot, result);
|
||||
resultType.loadAsTake(*this, ReturnSlot, result);
|
||||
emitScalarReturn(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,10 @@ namespace {
|
||||
IGF.emitLoadAndRetain(addr, e);
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
e.addUnmanaged(IGF.Builder.CreateLoad(addr));
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {
|
||||
IGF.emitAssignRetained(e.forwardNext(IGF), addr);
|
||||
}
|
||||
|
||||
@@ -222,6 +222,16 @@ namespace {
|
||||
IGF.emitLoadAndRetain(projectOwner(IGF, address), e);
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address address, Explosion &e) const {
|
||||
// Load the reference.
|
||||
Address refAddr = projectReference(IGF, address);
|
||||
e.addUnmanaged(IGF.Builder.CreateLoad(refAddr));
|
||||
|
||||
// Load the owner.
|
||||
Address ownerAddr = projectOwner(IGF, address);
|
||||
e.addUnmanaged(IGF.Builder.CreateLoad(ownerAddr));
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address address) const {
|
||||
// Store the reference.
|
||||
IGF.Builder.CreateStore(e.claimUnmanagedNext(),
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace {
|
||||
unsigned getExplosionSize(ExplosionKind kind) const { return 0; }
|
||||
void getSchema(ExplosionSchema &schema) const {}
|
||||
void load(IRGenFunction &IGF, Address addr, Explosion &e) const {}
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {}
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {}
|
||||
void initialize(IRGenFunction &IGF, Explosion &e, Address addr) const {}
|
||||
void reexplode(IRGenFunction &IGF, Explosion &src, Explosion &dest) const {}
|
||||
|
||||
@@ -96,6 +96,10 @@ namespace {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {
|
||||
// FIXME
|
||||
}
|
||||
@@ -157,6 +161,11 @@ namespace {
|
||||
Singleton->load(IGF, getSingletonAddress(IGF, addr), e);
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
if (!Singleton) return;
|
||||
Singleton->loadAsTake(IGF, getSingletonAddress(IGF, addr), e);
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {
|
||||
if (!Singleton) return;
|
||||
Singleton->assign(IGF, e, getSingletonAddress(IGF, addr));
|
||||
@@ -230,6 +239,10 @@ namespace {
|
||||
addr->getName() + ".load"));
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
return EnumTypeInfo::load(IGF, addr, e);
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {
|
||||
assert(isComplete());
|
||||
IGF.Builder.CreateStore(e.claimUnmanagedNext(), projectValue(IGF, addr));
|
||||
|
||||
@@ -176,6 +176,16 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
for (auto &field : getFieldInfos()) {
|
||||
// Ignore fields that don't have storage.
|
||||
if (!field.hasStorage()) continue;
|
||||
|
||||
Address fieldAddr = projectAddress(IGF, addr, field);
|
||||
field.Type.loadAsTake(IGF, fieldAddr, e);
|
||||
}
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {
|
||||
for (auto &field : getFieldInfos()) {
|
||||
// Ignore fields that don't have storage.
|
||||
|
||||
@@ -52,7 +52,7 @@ void TypeInfo::initializeWithTake(IRGenFunction &IGF,
|
||||
ExplosionSchema schema = getSchema(ExplosionKind::Maximal);
|
||||
if (!schema.containsAggregate() && schema.size() <= 2) {
|
||||
Explosion copy(ExplosionKind::Maximal);
|
||||
load(IGF, srcAddr, copy);
|
||||
loadAsTake(IGF, srcAddr, copy);
|
||||
initialize(IGF, copy, destAddr);
|
||||
return;
|
||||
}
|
||||
@@ -102,6 +102,10 @@ namespace {
|
||||
e.addUnmanaged(IGF.Builder.CreateLoad(addr));
|
||||
}
|
||||
|
||||
void loadAsTake(IRGenFunction &IGF, Address addr, Explosion &e) const {
|
||||
return PrimitiveTypeInfo::load(IGF, addr, e);
|
||||
}
|
||||
|
||||
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const {
|
||||
IGF.Builder.CreateStore(e.claimUnmanagedNext(), addr);
|
||||
}
|
||||
|
||||
@@ -122,10 +122,16 @@ public:
|
||||
/// Return the number of elements in an explosion of this type.
|
||||
virtual unsigned getExplosionSize(ExplosionKind kind) const = 0;
|
||||
|
||||
/// Load a list of exploded values from an address.
|
||||
/// Load an explosion of values from an address.
|
||||
virtual void load(IRGenFunction &IGF, Address addr,
|
||||
Explosion &explosion) const = 0;
|
||||
|
||||
/// Perform a 'take' load of the given address. This is like a C++
|
||||
/// move-initialization, except that the object at the old address
|
||||
/// will not be destroyed.
|
||||
virtual void loadAsTake(IRGenFunction &IGF, Address addr,
|
||||
Explosion &explosion) const = 0;
|
||||
|
||||
/// Assign a set of exploded values into an address. The values are
|
||||
/// consumed out of the explosion.
|
||||
virtual void assign(IRGenFunction &IGF, Explosion &explosion,
|
||||
|
||||
Reference in New Issue
Block a user