mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
remove the Cleanup subclasses.
Swift SVN r4839
This commit is contained in:
@@ -29,7 +29,6 @@ namespace irgen {
|
||||
class Cleanup {
|
||||
unsigned AllocatedSize;
|
||||
unsigned State : 2;
|
||||
llvm::BasicBlock *NormalEntryBB;
|
||||
|
||||
friend Cleanup &IRGenFunction::initCleanup(Cleanup &, size_t, CleanupState);
|
||||
protected:
|
||||
@@ -51,11 +50,6 @@ public:
|
||||
bool isActive() const { return getState() == CleanupState::Active; }
|
||||
bool isDead() const { return getState() == CleanupState::Dead; }
|
||||
|
||||
llvm::BasicBlock *getNormalEntryBlock() const { return NormalEntryBB; }
|
||||
void setNormalEntryBlock(llvm::BasicBlock *BB) { NormalEntryBB = BB; }
|
||||
|
||||
virtual void emit(IRGenFunction &IGF) const = 0;
|
||||
|
||||
private:
|
||||
virtual void _anchor();
|
||||
};
|
||||
|
||||
@@ -425,32 +425,6 @@ OwnedAddress irgen::projectPhysicalClassMemberAddress(IRGenFunction &IGF,
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
class ClassDestroyCleanup : public Cleanup {
|
||||
llvm::Value *ThisValue;
|
||||
const ClassTypeInfo &info;
|
||||
|
||||
public:
|
||||
ClassDestroyCleanup(llvm::Value *ThisValue, const ClassTypeInfo &info)
|
||||
: ThisValue(ThisValue), info(info) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
// FIXME: This implementation will be wrong once we get dynamic
|
||||
// class layout.
|
||||
auto &layout = info.getLayout(IGF.IGM);
|
||||
Address baseAddr = layout.emitCastTo(IGF, ThisValue);
|
||||
|
||||
// Destroy all the instance variables of the class.
|
||||
for (auto &field : layout.getElements()) {
|
||||
if (field.Type->isPOD(ResilienceScope::Local))
|
||||
continue;
|
||||
|
||||
field.Type->destroy(IGF, field.project(IGF, baseAddr));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Emit the deallocating destructor for a class in terms of its destroying
|
||||
/// destructor.
|
||||
void irgen::emitDeallocatingDestructor(IRGenModule &IGM,
|
||||
|
||||
@@ -111,8 +111,6 @@ Cleanup &IRGenFunction::initCleanup(Cleanup &cleanup, size_t allocSize,
|
||||
CleanupState state) {
|
||||
cleanup.AllocatedSize = allocSize;
|
||||
cleanup.State = unsigned(state);
|
||||
cleanup.NormalEntryBB = nullptr;
|
||||
|
||||
|
||||
return cleanup;
|
||||
}
|
||||
@@ -120,12 +118,6 @@ Cleanup &IRGenFunction::initCleanup(Cleanup &cleanup, size_t allocSize,
|
||||
/// Change the state of a cleanup.
|
||||
void IRGenFunction::setCleanupState(CleanupsDepth depth,
|
||||
CleanupState newState) {
|
||||
auto iter = Cleanups.find(depth);
|
||||
assert(iter != Cleanups.end() && "changing state of end of stack");
|
||||
setCleanupState(*iter, newState);
|
||||
|
||||
if (newState == CleanupState::Dead && iter == Cleanups.begin())
|
||||
popAndEmitTopDeadCleanups(*this, Cleanups, InnermostScope);
|
||||
}
|
||||
|
||||
void IRGenFunction::setCleanupState(Cleanup &cleanup, CleanupState newState) {
|
||||
|
||||
@@ -629,14 +629,14 @@ static void emitReleaseCall(IRGenFunction &IGF, llvm::Value *value) {
|
||||
llvm::Constant *fn = IGF.IGM.getReleaseFn();
|
||||
if (value->getType() != IGF.IGM.RefCountedPtrTy) {
|
||||
llvm::FunctionType *fnType =
|
||||
llvm::FunctionType::get(IGF.IGM.VoidTy, value->getType(), false);
|
||||
llvm::FunctionType::get(IGF.IGM.VoidTy, value->getType(), false);
|
||||
fn = llvm::ConstantExpr::getBitCast(fn, fnType->getPointerTo());
|
||||
}
|
||||
|
||||
|
||||
// The call itself can never throw.
|
||||
llvm::CallInst *call = IGF.Builder.CreateCall(fn, value);
|
||||
call->setCallingConv(IGF.IGM.RuntimeCC);
|
||||
call->setDoesNotThrow();
|
||||
call->setDoesNotThrow();
|
||||
}
|
||||
|
||||
/// Emit a release of a live value.
|
||||
@@ -645,45 +645,11 @@ void IRGenFunction::emitRelease(llvm::Value *value) {
|
||||
return emitReleaseCall(*this, value);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct CallRelease : Cleanup {
|
||||
llvm::Value *Value;
|
||||
CallRelease(llvm::Value *value) : Value(value) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
emitReleaseCall(IGF, Value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Enter a cleanup to release an object.
|
||||
ManagedValue IRGenFunction::enterReleaseCleanup(llvm::Value *value) {
|
||||
if (doesNotRequireRefCounting(value))
|
||||
return ManagedValue(value);
|
||||
|
||||
pushFullExprCleanup<CallRelease>(value);
|
||||
return ManagedValue(value, getCleanupsDepth());
|
||||
}
|
||||
|
||||
namespace {
|
||||
class CallDealloc : public Cleanup {
|
||||
llvm::Value *Allocation;
|
||||
llvm::Value *Size;
|
||||
public:
|
||||
CallDealloc(llvm::Value *allocation, llvm::Value *size)
|
||||
: Allocation(allocation), Size(size) {}
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
IGF.emitDeallocObjectCall(Allocation, Size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Enter a cleanup to call swift_dealloc on the given pointer.
|
||||
/// This cleanup will usually be deactivated as soon as the
|
||||
/// initializer completes.
|
||||
CleanupsDepth
|
||||
IRGenFunction::pushDeallocCleanup(llvm::Value *allocation,
|
||||
llvm::Value *size) {
|
||||
pushFullExprCleanup<CallDealloc>(allocation, size);
|
||||
return getCleanupsDepth();
|
||||
}
|
||||
|
||||
@@ -34,73 +34,24 @@
|
||||
using namespace swift;
|
||||
using namespace irgen;
|
||||
|
||||
namespace {
|
||||
/// A cleanup to destroy an object whose address isn't actually known yet.
|
||||
class UnboundDestroy : public Cleanup {
|
||||
const TypeInfo &TI;
|
||||
OwnedAddress Addr;
|
||||
|
||||
public:
|
||||
UnboundDestroy(const TypeInfo &TI) : TI(TI) {}
|
||||
|
||||
void setAddress(OwnedAddress addr) {
|
||||
assert(!Addr.isValid());
|
||||
Addr = addr;
|
||||
}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
assert(Addr.isValid());
|
||||
llvm::Value *owner = Addr.getOwner();
|
||||
if (!isa<llvm::ConstantPointerNull>(owner)) {
|
||||
IGF.emitRelease(owner);
|
||||
} else {
|
||||
TI.destroy(IGF, Addr);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Enter a cleanup to destroy an object of arbitrary type. Adds the
|
||||
/// address value to the given explosion, along with the appropriate
|
||||
/// cleanup.
|
||||
void IRGenFunction::enterDestroyCleanup(Address addr,
|
||||
const TypeInfo &addrTI,
|
||||
Explosion &out) {
|
||||
enterDestroyCleanup(addr, addrTI);
|
||||
out.add(ManagedValue(addr.getAddress(), getCleanupsDepth()));
|
||||
}
|
||||
|
||||
/// Enter a cleanup to destroy an object of arbitrary type.
|
||||
void IRGenFunction::enterDestroyCleanup(Address addr,
|
||||
const TypeInfo &addrTI) {
|
||||
assert(!addrTI.isPOD(ResilienceScope::Local) &&
|
||||
"destroying something known to be POD");
|
||||
|
||||
// The use of UnboundDestroy here is not important.
|
||||
UnboundDestroy &destroy = pushCleanup<UnboundDestroy>(addrTI);
|
||||
destroy.setAddress(OwnedAddress(addr, IGM.RefCountedNull));
|
||||
}
|
||||
|
||||
/// Register an object with the initialization process.
|
||||
CleanupsDepth Initialization::registerObject(IRGenFunction &IGF,
|
||||
InitializedObject object,
|
||||
OnHeap_t onHeap,
|
||||
const TypeInfo &objectTI) {
|
||||
// Create the appropriate destroy cleanup.
|
||||
CleanupsDepth destroy;
|
||||
registerObject(object, CleanupsDepth::invalid());
|
||||
|
||||
// We need a destroy cleanup if the object is on the heap or non-POD.
|
||||
if (onHeap || !objectTI.isPOD(ResilienceScope::Local)) {
|
||||
IGF.pushFullExprCleanupInState<UnboundDestroy>(CleanupState::Dormant,
|
||||
objectTI);
|
||||
destroy = IGF.getCleanupsDepth();
|
||||
} else {
|
||||
destroy = CleanupsDepth::invalid();
|
||||
}
|
||||
|
||||
registerObject(object, destroy);
|
||||
|
||||
return destroy;
|
||||
return CleanupsDepth::invalid();
|
||||
}
|
||||
|
||||
void Initialization::registerObjectWithoutDestroy(InitializedObject object) {
|
||||
@@ -128,13 +79,6 @@ void Initialization::markAllocated(IRGenFunction &IGF,
|
||||
"object was not registered with initialization");
|
||||
ValueRecord &record = Records.find(object.Opaque)->second;
|
||||
record.DeallocCleanup = dealloc;
|
||||
|
||||
// Update the destroy cleanup if present.
|
||||
if (record.DestroyCleanup.isValid()) {
|
||||
UnboundDestroy &destroy =
|
||||
static_cast<UnboundDestroy&>(IGF.findCleanup(record.DestroyCleanup));
|
||||
destroy.setAddress(address);
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a global variable.
|
||||
@@ -211,13 +155,8 @@ OwnedAddress FixedTypeInfo::allocate(IRGenFunction &IGF, Initialization &init,
|
||||
Address rawAddr = layout.emitCastTo(IGF, allocation);
|
||||
rawAddr = elt.project(IGF, rawAddr, name);
|
||||
|
||||
// Push a cleanup to dealloc the allocation.
|
||||
// FIXME: don't emit the size twice!
|
||||
CleanupsDepth deallocCleanup
|
||||
= IGF.pushDeallocCleanup(allocation, layout.emitSize(IGF));
|
||||
|
||||
OwnedAddress addr(rawAddr, allocation);
|
||||
init.markAllocated(IGF, object, addr, deallocCleanup);
|
||||
init.markAllocated(IGF, object, addr, CleanupsDepth::invalid());
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,19 +199,8 @@ static llvm::Value *emitObjCAutoreleaseReturnValue(IRGenFunction &IGF,
|
||||
return call;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct CallObjCRelease : Cleanup {
|
||||
llvm::Value *Value;
|
||||
CallObjCRelease(llvm::Value *value) : Value(value) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
IGF.emitObjCRelease(Value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ManagedValue IRGenFunction::enterObjCReleaseCleanup(llvm::Value *value) {
|
||||
pushFullExprCleanup<CallObjCRelease>(value);
|
||||
return ManagedValue(value, getCleanupsDepth());
|
||||
}
|
||||
|
||||
|
||||
@@ -468,18 +468,7 @@ static void emitDestroyBufferCall(IRGenFunction &IGF,
|
||||
setHelperAttributes(call);
|
||||
}
|
||||
|
||||
/// Emit a call to do a 'deallocateBuffer' operation.
|
||||
static void emitDeallocateBufferCall(IRGenFunction &IGF,
|
||||
llvm::Value *witnessTable,
|
||||
llvm::Value *metadata,
|
||||
Address buffer) {
|
||||
llvm::Value *fn = loadValueWitness(IGF, witnessTable,
|
||||
ValueWitness::DeallocateBuffer);
|
||||
llvm::CallInst *call =
|
||||
IGF.Builder.CreateCall2(fn, buffer.getAddress(), metadata);
|
||||
call->setCallingConv(IGF.IGM.RuntimeCC);
|
||||
setHelperAttributes(call);
|
||||
}
|
||||
|
||||
|
||||
/// Given the address of an existential object, destroy it.
|
||||
static void emitDestroyExistential(IRGenFunction &IGF, Address addr,
|
||||
@@ -500,51 +489,6 @@ static llvm::Constant *getAssignExistentialsFunction(IRGenModule &IGM,
|
||||
ExistentialLayout layout);
|
||||
|
||||
namespace {
|
||||
struct DestroyBuffer : Cleanup {
|
||||
Address Buffer;
|
||||
llvm::Value *Table;
|
||||
llvm::Value *Metatype;
|
||||
DestroyBuffer(Address buffer, llvm::Value *table, llvm::Value *metatype)
|
||||
: Buffer(buffer), Table(table), Metatype(metatype) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
emitDestroyBufferCall(IGF, Table, Metatype, Buffer);
|
||||
}
|
||||
};
|
||||
|
||||
struct DeallocateBuffer : Cleanup {
|
||||
Address Buffer;
|
||||
llvm::Value *Table;
|
||||
llvm::Value *Metatype;
|
||||
DeallocateBuffer(Address buffer, llvm::Value *table, llvm::Value *metatype)
|
||||
: Buffer(buffer), Table(table), Metatype(metatype) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
emitDeallocateBufferCall(IGF, Table, Metatype, Buffer);
|
||||
}
|
||||
};
|
||||
|
||||
struct DeallocateBox : Cleanup {
|
||||
llvm::Value *Box;
|
||||
llvm::Value *Type;
|
||||
DeallocateBox(llvm::Value *box, llvm::Value *type)
|
||||
: Box(box), Type(type) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
IGF.emitDeallocBoxCall(Box, Type);
|
||||
}
|
||||
};
|
||||
|
||||
struct DestroyExistential : Cleanup {
|
||||
ExistentialLayout Layout;
|
||||
Address Addr;
|
||||
DestroyExistential(ExistentialLayout layout, Address addr)
|
||||
: Layout(layout), Addr(addr) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
emitDestroyExistential(IGF, Addr, Layout);
|
||||
}
|
||||
};
|
||||
|
||||
/// A CRTP class for visiting the witnesses of a protocol.
|
||||
///
|
||||
@@ -1011,10 +955,8 @@ namespace {
|
||||
Address rawAddr(address, Alignment(1));
|
||||
|
||||
// Push a cleanup to dealloc the allocation.
|
||||
IGF.pushCleanup<DeallocateBox>(box, metadata);
|
||||
CleanupsDepth dealloc = IGF.getCleanupsDepth();
|
||||
OwnedAddress addr(rawAddr, box);
|
||||
init.markAllocated(IGF, object, addr, dealloc);
|
||||
init.markAllocated(IGF, object, addr, IGF.getCleanupsDepth());
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1031,9 +973,7 @@ namespace {
|
||||
OwnedAddress ownedAddr(allocated, IGF.IGM.RefCountedNull);
|
||||
|
||||
// Push a cleanup to dealloc it.
|
||||
IGF.pushCleanup<DeallocateBuffer>(buffer, wtable, metadata);
|
||||
CleanupsDepth dealloc = IGF.getCleanupsDepth();
|
||||
init.markAllocated(IGF, object, ownedAddr, dealloc);
|
||||
init.markAllocated(IGF, object, ownedAddr, IGF.getCleanupsDepth());
|
||||
return ownedAddr;
|
||||
}
|
||||
|
||||
@@ -1452,26 +1392,6 @@ static void emitDeallocateBuffer(IRGenFunction &IGF,
|
||||
}
|
||||
llvm_unreachable("bad packing!");
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// A cleanup for deallocating a buffer when the concrete type
|
||||
/// stored there is known.
|
||||
class DeallocateConcreteBuffer : public Cleanup {
|
||||
Address Buffer;
|
||||
FixedPacking Packing;
|
||||
const TypeInfo &ConcreteTI;
|
||||
|
||||
public:
|
||||
DeallocateConcreteBuffer(Address buffer, FixedPacking packing,
|
||||
const TypeInfo &concreteTI)
|
||||
: Buffer(buffer), Packing(packing), ConcreteTI(concreteTI) {}
|
||||
|
||||
void emit(IRGenFunction &IGF) const {
|
||||
emitDeallocateBuffer(IGF, ConcreteTI, Packing, Buffer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Emit a 'destroyObject' operation.
|
||||
static void emitDestroyObject(IRGenFunction &IGF,
|
||||
const TypeInfo &type,
|
||||
|
||||
@@ -187,18 +187,6 @@ void IRGenFunction::emitDeallocRawCall(llvm::Value *pointer,
|
||||
return emitDeallocatingCall(*this, IGM.getSlowRawDeallocFn(), pointer, size);
|
||||
}
|
||||
|
||||
/// Deallocate an object which was allocated but has not actually been
|
||||
/// initialized.
|
||||
void IRGenFunction::emitDeallocObjectCall(llvm::Value *ptr, llvm::Value *size) {
|
||||
// For now, all we have is swift_deallocObject.
|
||||
return emitDeallocatingCall(*this, IGM.getDeallocObjectFn(), ptr, size);
|
||||
}
|
||||
|
||||
void IRGenFunction::emitDeallocBoxCall(llvm::Value *box, llvm::Value *type) {
|
||||
llvm::CallInst *call = Builder.CreateCall2(IGM.getDeallocBoxFn(), box, type);
|
||||
call->setCallingConv(IGM.RuntimeCC);
|
||||
call->setDoesNotThrow();
|
||||
}
|
||||
|
||||
void IRGenFunction::unimplemented(SourceLoc Loc, StringRef Message) {
|
||||
return IGM.unimplemented(Loc, Message);
|
||||
|
||||
@@ -199,7 +199,6 @@ public:
|
||||
|
||||
void enterDestroyCleanup(Address addr, const TypeInfo &addrTI,
|
||||
Explosion &out);
|
||||
void enterDestroyCleanup(Address addr, const TypeInfo &addrTI);
|
||||
|
||||
/// Is the current emission point conditionally evaluated? Right
|
||||
/// now we don't have any expressions which introduce conditional
|
||||
@@ -256,7 +255,6 @@ public:
|
||||
llvm::Value *emitAllocObjectCall(llvm::Value *metadata, llvm::Value *size,
|
||||
llvm::Value *align,
|
||||
const llvm::Twine &name = "");
|
||||
void emitDeallocObjectCall(llvm::Value *pointer, llvm::Value *size);
|
||||
llvm::Value *emitAllocRawCall(llvm::Value *size, llvm::Value *align,
|
||||
const llvm::Twine &name ="");
|
||||
void emitDeallocRawCall(llvm::Value *pointer, llvm::Value *size);
|
||||
@@ -264,7 +262,6 @@ public:
|
||||
void emitAllocBoxCall(llvm::Value *typeMetadata,
|
||||
llvm::Value *&box,
|
||||
llvm::Value *&valueAddress);
|
||||
void emitDeallocBoxCall(llvm::Value *box, llvm::Value *type);
|
||||
|
||||
private:
|
||||
llvm::Instruction *AllocaIP;
|
||||
@@ -273,8 +270,6 @@ private:
|
||||
public:
|
||||
llvm::Value *emitUnmanagedAlloc(const HeapLayout &layout,
|
||||
const llvm::Twine &name);
|
||||
CleanupsDepth pushDeallocCleanup(llvm::Value *allocation,
|
||||
llvm::Value *size);
|
||||
void emitLoadAndRetain(Address addr, Explosion &explosion);
|
||||
void emitAssignRetained(llvm::Value *value, Address addr);
|
||||
void emitInitializeRetained(llvm::Value *value, Address addr);
|
||||
|
||||
@@ -57,8 +57,6 @@ IRGenModule::IRGenModule(ASTContext &Context,
|
||||
AllocBoxFn = nullptr;
|
||||
RetainNoResultFn = nullptr;
|
||||
ReleaseFn = nullptr;
|
||||
DeallocObjectFn = nullptr;
|
||||
DeallocBoxFn = nullptr;
|
||||
ObjCRetainFn = nullptr;
|
||||
ObjCReleaseFn = nullptr;
|
||||
RawAllocFn = nullptr;
|
||||
@@ -364,28 +362,6 @@ llvm::Constant *IRGenModule::getReleaseFn() {
|
||||
return ReleaseFn;
|
||||
}
|
||||
|
||||
llvm::Constant *IRGenModule::getDeallocObjectFn() {
|
||||
if (DeallocObjectFn) return DeallocObjectFn;
|
||||
|
||||
// void swift_deallocObject(void *ptr, size_t size);
|
||||
llvm::Type *argTypes[] = { RefCountedPtrTy, SizeTy };
|
||||
llvm::FunctionType *fnType =
|
||||
llvm::FunctionType::get(VoidTy, argTypes, false);
|
||||
DeallocObjectFn = createRuntimeFunction(*this, "swift_deallocObject", fnType);
|
||||
return DeallocObjectFn;
|
||||
}
|
||||
|
||||
llvm::Constant *IRGenModule::getDeallocBoxFn() {
|
||||
if (DeallocObjectFn) return DeallocBoxFn;
|
||||
|
||||
// void swift_deallocBox(void *ptr, Metadata *type);
|
||||
llvm::Type *argTypes[] = { RefCountedPtrTy, TypeMetadataPtrTy };
|
||||
llvm::FunctionType *fnType =
|
||||
llvm::FunctionType::get(VoidTy, argTypes, false);
|
||||
DeallocObjectFn = createRuntimeFunction(*this, "swift_deallocBox", fnType);
|
||||
return DeallocObjectFn;
|
||||
}
|
||||
|
||||
llvm::Constant *IRGenModule::getGetFunctionMetadataFn() {
|
||||
if (GetFunctionMetadataFn) return GetFunctionMetadataFn;
|
||||
|
||||
|
||||
@@ -222,9 +222,7 @@ public:
|
||||
llvm::Constant *getAllocBoxFn();
|
||||
llvm::Constant *getRetainNoResultFn();
|
||||
llvm::Constant *getReleaseFn();
|
||||
llvm::Constant *getDeallocObjectFn();
|
||||
llvm::Constant *getDeallocBoxFn();
|
||||
|
||||
|
||||
llvm::Constant *getRawAllocFn();
|
||||
llvm::Constant *getRawDeallocFn();
|
||||
llvm::Constant *getSlowAllocFn();
|
||||
@@ -266,8 +264,6 @@ private:
|
||||
llvm::Constant *AllocBoxFn;
|
||||
llvm::Constant *RetainNoResultFn;
|
||||
llvm::Constant *ReleaseFn;
|
||||
llvm::Constant *DeallocObjectFn;
|
||||
llvm::Constant *DeallocBoxFn;
|
||||
llvm::Constant *RawAllocFn;
|
||||
llvm::Constant *RawDeallocFn;
|
||||
llvm::Constant *SlowAllocFn;
|
||||
|
||||
Reference in New Issue
Block a user