mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When we partially apply an inner-pointer method or property, the thunk or partial_apply that applies "self" needs to be the one that handles lifetime-extending "self". Verify that a partial_apply-ed inner pointer method is not inner pointer and implement lifetime extension in the partial apply thunk. Fixes <rdar://problem/16803701>. Swift SVN r17321
287 lines
10 KiB
C++
287 lines
10 KiB
C++
//===--- IRGenFunction.h - IR Generation for Swift Functions ---*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the structure used to generate the IR body of a
|
|
// function.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_IRGEN_IRGENFUNCTION_H
|
|
#define SWIFT_IRGEN_IRGENFUNCTION_H
|
|
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/AST/Type.h"
|
|
#include "swift/SIL/SILLocation.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/IR/CallingConv.h"
|
|
#include "IRBuilder.h"
|
|
|
|
|
|
namespace llvm {
|
|
class AllocaInst;
|
|
class CallSite;
|
|
class Constant;
|
|
class Function;
|
|
}
|
|
|
|
namespace swift {
|
|
class ArchetypeType;
|
|
class ClassDecl;
|
|
class ConstructorDecl;
|
|
class Decl;
|
|
class ExtensionDecl;
|
|
class FuncDecl;
|
|
class EnumElementDecl;
|
|
class EnumType;
|
|
template<typename T> class Optional;
|
|
class Pattern;
|
|
class PatternBindingDecl;
|
|
class SILDebugScope;
|
|
class SILType;
|
|
class SourceLoc;
|
|
class StructType;
|
|
class Substitution;
|
|
class ValueDecl;
|
|
class VarDecl;
|
|
|
|
namespace irgen {
|
|
enum class CheckedCastMode : unsigned char;
|
|
class Explosion;
|
|
class FunctionRef;
|
|
class HeapLayout;
|
|
class IRGenModule;
|
|
class LinkEntity;
|
|
class Scope;
|
|
class TypeInfo;
|
|
|
|
/// LocalTypeData - A nonce value for storing some sort of
|
|
/// locally-known information about a type.
|
|
///
|
|
/// The enumerated values are all in the "negative" range and so do
|
|
/// not collide with reasonable index values.
|
|
enum class LocalTypeData : unsigned {
|
|
/// A reference to a metatype.
|
|
Metatype = ~0U
|
|
};
|
|
|
|
/// Discriminator for checked cast modes.
|
|
enum class CheckedCastMode : unsigned char {
|
|
Unconditional,
|
|
Conditional,
|
|
};
|
|
|
|
/// IRGenFunction - Primary class for emitting LLVM instructions for a
|
|
/// specific function.
|
|
class IRGenFunction {
|
|
public:
|
|
IRGenModule &IGM;
|
|
IRBuilder Builder;
|
|
|
|
llvm::Function *CurFn;
|
|
llvm::Value *ContextPtr;
|
|
|
|
IRGenFunction(IRGenModule &IGM,
|
|
llvm::Function *fn,
|
|
SILDebugScope* DbgScope = nullptr,
|
|
Optional<SILLocation> DbgLoc = Nothing);
|
|
~IRGenFunction();
|
|
|
|
void unimplemented(SourceLoc Loc, StringRef Message);
|
|
|
|
friend class Scope;
|
|
|
|
//--- Function prologue and epilogue -------------------------------------------
|
|
public:
|
|
Explosion collectParameters(ResilienceExpansion explosionLevel);
|
|
void emitScalarReturn(SILType resultTy, Explosion &scalars);
|
|
|
|
void emitBBForReturn();
|
|
bool emitBranchToReturnBB();
|
|
|
|
private:
|
|
void emitPrologue();
|
|
void emitEpilogue();
|
|
|
|
Address ReturnSlot;
|
|
llvm::BasicBlock *ReturnBB;
|
|
|
|
//--- Helper methods -----------------------------------------------------------
|
|
public:
|
|
Address createAlloca(llvm::Type *ty, Alignment align,
|
|
const llvm::Twine &name);
|
|
|
|
llvm::BasicBlock *createBasicBlock(const llvm::Twine &Name);
|
|
const TypeInfo &getTypeInfoForUnlowered(Type subst);
|
|
const TypeInfo &getTypeInfoForUnlowered(AbstractionPattern orig, Type subst);
|
|
const TypeInfo &getTypeInfoForUnlowered(AbstractionPattern orig,
|
|
CanType subst);
|
|
const TypeInfo &getTypeInfoForLowered(CanType T);
|
|
const TypeInfo &getTypeInfo(SILType T);
|
|
void emitMemCpy(llvm::Value *dest, llvm::Value *src,
|
|
Size size, Alignment align);
|
|
void emitMemCpy(llvm::Value *dest, llvm::Value *src,
|
|
llvm::Value *size, Alignment align);
|
|
void emitMemCpy(Address dest, Address src, Size size);
|
|
void emitMemCpy(Address dest, Address src, llvm::Value *size);
|
|
|
|
llvm::Value *emitByteOffsetGEP(llvm::Value *base, llvm::Value *offset,
|
|
llvm::Type *objectType,
|
|
const llvm::Twine &name = "");
|
|
Address emitByteOffsetGEP(llvm::Value *base, llvm::Value *offset,
|
|
const TypeInfo &type,
|
|
const llvm::Twine &name = "");
|
|
|
|
llvm::Value *emitAllocObjectCall(llvm::Value *metadata, llvm::Value *size,
|
|
llvm::Value *alignMask,
|
|
const llvm::Twine &name = "");
|
|
llvm::Value *emitAllocRawCall(llvm::Value *size, llvm::Value *alignMask,
|
|
const llvm::Twine &name ="");
|
|
void emitDeallocRawCall(llvm::Value *pointer, llvm::Value *size);
|
|
|
|
void emitAllocBoxCall(llvm::Value *typeMetadata,
|
|
llvm::Value *&box,
|
|
llvm::Value *&valueAddress);
|
|
|
|
llvm::Value *emitTypeMetadataRef(CanType type);
|
|
llvm::Value *emitTypeMetadataRef(SILType type);
|
|
llvm::Value *emitValueWitnessTableRefForMetadata(llvm::Value *metadata);
|
|
|
|
/// Emit a load of a reference to the given Objective-C selector.
|
|
llvm::Value *emitObjCSelectorRefLoad(StringRef selector);
|
|
|
|
/// Return the SILDebugScope for this function.
|
|
SILDebugScope* getDebugScope() const { return DbgScope; }
|
|
llvm::Value *coerceValue(llvm::Value *value, llvm::Type *toTy,
|
|
const llvm::DataLayout &);
|
|
|
|
private:
|
|
llvm::Instruction *AllocaIP;
|
|
SILDebugScope* DbgScope;
|
|
|
|
//--- Reference-counting methods -----------------------------------------------
|
|
public:
|
|
llvm::Value *emitUnmanagedAlloc(const HeapLayout &layout,
|
|
const llvm::Twine &name);
|
|
void emitLoadAndRetain(Address addr, Explosion &explosion);
|
|
void emitAssignRetained(llvm::Value *value, Address addr);
|
|
void emitInitializeRetained(llvm::Value *value, Address addr);
|
|
void emitRetain(llvm::Value *value, Explosion &explosion);
|
|
void emitRetainCall(llvm::Value *value);
|
|
void emitRelease(llvm::Value *value);
|
|
void emitRetainUnowned(llvm::Value *value);
|
|
void emitUnownedRetain(llvm::Value *value);
|
|
void emitUnownedRelease(llvm::Value *value);
|
|
void emitWeakInit(llvm::Value *value, Address dest);
|
|
void emitWeakAssign(llvm::Value *value, Address dest);
|
|
llvm::Value *emitWeakLoadStrong(Address src, llvm::Type *type);
|
|
llvm::Value *emitWeakTakeStrong(Address src, llvm::Type *type);
|
|
void emitWeakDestroy(Address addr);
|
|
void emitWeakCopyInit(Address destAddr, Address srcAddr);
|
|
void emitWeakTakeInit(Address destAddr, Address srcAddr);
|
|
void emitWeakCopyAssign(Address destAddr, Address srcAddr);
|
|
void emitWeakTakeAssign(Address destAddr, Address srcAddr);
|
|
void emitObjCRetain(llvm::Value *value, Explosion &explosion);
|
|
llvm::Value *emitObjCRetainCall(llvm::Value *value);
|
|
llvm::Value *emitObjCAutoreleaseCall(llvm::Value *value);
|
|
void emitObjCRelease(llvm::Value *value);
|
|
llvm::Value *emitBlockCopyCall(llvm::Value *value);
|
|
void emitBlockRelease(llvm::Value *value);
|
|
|
|
/// Emit a retain of a class instance with unknown retain semantics.
|
|
void emitUnknownRetain(llvm::Value *value, Explosion &explosion);
|
|
/// Emit a retain of a class instance with unknown retain semantics, and
|
|
/// return the retained value.
|
|
llvm::Value *emitUnknownRetainCall(llvm::Value *value);
|
|
/// Emit a release of a class instance with unknown retain semantics.
|
|
void emitUnknownRelease(llvm::Value *value);
|
|
void emitUnknownUnownedRetain(llvm::Value *value);
|
|
void emitUnknownUnownedRelease(llvm::Value *value);
|
|
void emitUnknownRetainUnowned(llvm::Value *value);
|
|
void emitUnknownWeakDestroy(Address addr);
|
|
void emitUnknownWeakCopyInit(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakTakeInit(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakCopyAssign(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakTakeAssign(Address destAddr, Address srcAddr);
|
|
void emitUnknownWeakInit(llvm::Value *value, Address dest);
|
|
void emitUnknownWeakAssign(llvm::Value *value, Address dest);
|
|
llvm::Value *emitUnknownWeakLoadStrong(Address src, llvm::Type *type);
|
|
llvm::Value *emitUnknownWeakTakeStrong(Address src, llvm::Type *type);
|
|
|
|
//--- Expression emission ------------------------------------------------------
|
|
public:
|
|
void emitFakeExplosion(const TypeInfo &type, Explosion &explosion);
|
|
|
|
/// \brief Convert the given explosion to the given destination archetype,
|
|
/// using a runtime-checked cast.
|
|
llvm::Value *emitSuperToClassArchetypeConversion(llvm::Value *super,
|
|
SILType destType,
|
|
CheckedCastMode mode);
|
|
|
|
/// \brief Convert the given value to the given destination type, using a
|
|
/// runtime-checked cast.
|
|
llvm::Value *emitDowncast(llvm::Value *from,
|
|
SILType toType,
|
|
CheckedCastMode mode);
|
|
|
|
|
|
//--- Declaration emission -----------------------------------------------------
|
|
public:
|
|
|
|
void bindArchetype(ArchetypeType *type,
|
|
llvm::Value *metadata,
|
|
ArrayRef<llvm::Value*> wtables);
|
|
|
|
//--- Type emission ------------------------------------------------------------
|
|
public:
|
|
/// Look for a mapping for a local type-metadata reference.
|
|
llvm::Value *tryGetLocalTypeData(CanType type, LocalTypeData index) {
|
|
auto key = getLocalTypeDataKey(type, index);
|
|
auto it = LocalTypeDataMap.find(key);
|
|
if (it == LocalTypeDataMap.end())
|
|
return nullptr;
|
|
return it->second;
|
|
}
|
|
|
|
/// Retrieve a local type-metadata reference which is known to exist.
|
|
llvm::Value *getLocalTypeData(CanType type, LocalTypeData index) {
|
|
auto key = getLocalTypeDataKey(type, index);
|
|
assert(LocalTypeDataMap.count(key) && "no mapping for local type data");
|
|
return LocalTypeDataMap.find(key)->second;
|
|
}
|
|
|
|
/// Add a local type-metadata reference at a point which dominates
|
|
/// the entire function.
|
|
void setUnscopedLocalTypeData(CanType type, LocalTypeData index,
|
|
llvm::Value *data) {
|
|
assert(data && "setting a null value for type data!");
|
|
|
|
auto key = getLocalTypeDataKey(type, index);
|
|
assert(!LocalTypeDataMap.count(key) &&
|
|
"existing mapping for local type data");
|
|
LocalTypeDataMap.insert(std::make_pair(key, data));
|
|
}
|
|
|
|
private:
|
|
typedef unsigned LocalTypeDataDepth;
|
|
typedef std::pair<TypeBase*,unsigned> LocalTypeDataPair;
|
|
LocalTypeDataPair getLocalTypeDataKey(CanType type, LocalTypeData index) {
|
|
return LocalTypeDataPair(type.getPointer(), unsigned(index));
|
|
}
|
|
|
|
llvm::DenseMap<LocalTypeDataPair, llvm::Value*> LocalTypeDataMap;
|
|
};
|
|
|
|
} // end namespace irgen
|
|
} // end namespace swift
|
|
|
|
#endif
|