Skip to content

[Async CC] Add constant "pointer" for async func. #34589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ class LinkEntity {
/// the metadata cache once.
CanonicalPrespecializedGenericTypeCachingOnceToken,

/// The same as AsyncFunctionPointer but with a different stored value, for
/// use by TBDGen.
/// The pointer is a AbstractStorageDecl*.
AsyncFunctionPointerAST,

/// The pointer is a SILFunction*.
DynamicallyReplaceableFunctionKey,

Expand Down Expand Up @@ -410,6 +415,13 @@ class LinkEntity {
/// passed to swift_getCanonicalSpecializedMetadata.
/// The pointer is a canonical TypeBase*.
NoncanonicalSpecializedGenericTypeMetadataCacheVariable,

/// Provides the data required to invoke an async function using the async
/// calling convention in the form of the size of the context to allocate
/// and the relative address of the function to call with that allocated
/// context.
/// The pointer is a SILFunction*.
AsyncFunctionPointer,
};
friend struct llvm::DenseMapInfo<LinkEntity>;

Expand All @@ -418,7 +430,7 @@ class LinkEntity {
}

static bool isDeclKind(Kind k) {
return k <= Kind::CanonicalPrespecializedGenericTypeCachingOnceToken;
return k <= Kind::AsyncFunctionPointerAST;
}
static bool isTypeKind(Kind k) {
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
Expand Down Expand Up @@ -1088,6 +1100,21 @@ class LinkEntity {
return entity;
}

static LinkEntity forAsyncFunctionPointer(SILFunction *silFunction) {
LinkEntity entity;
entity.Pointer = silFunction;
entity.SecondaryPointer = nullptr;
entity.Data = LINKENTITY_SET_FIELD(
Kind, unsigned(LinkEntity::Kind::AsyncFunctionPointer));
return entity;
}

static LinkEntity forAsyncFunctionPointer(AbstractFunctionDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::AsyncFunctionPointerAST, decl);
return entity;
}

void mangle(llvm::raw_ostream &out) const;
void mangle(SmallVectorImpl<char> &buffer) const;
std::string mangleAsString() const;
Expand All @@ -1110,14 +1137,15 @@ class LinkEntity {
}

bool hasSILFunction() const {
return getKind() == Kind::SILFunction ||
return getKind() == Kind::AsyncFunctionPointer ||
getKind() == Kind::DynamicallyReplaceableFunctionVariable ||
getKind() == Kind::DynamicallyReplaceableFunctionKey;
getKind() == Kind::DynamicallyReplaceableFunctionKey ||
getKind() == Kind::SILFunction;
}

SILFunction *getSILFunction() const {
assert(hasSILFunction());
return reinterpret_cast<SILFunction*>(Pointer);
return reinterpret_cast<SILFunction *>(Pointer);
}

SILGlobalVariable *getSILGlobalVariable() const {
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/CallEmission.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class CallEmission {
void emitToUnmappedExplosion(Explosion &out);
virtual void emitCallToUnmappedExplosion(llvm::CallInst *call, Explosion &out) = 0;
void emitYieldsToExplosion(Explosion &out);
virtual FunctionPointer getCalleeFunctionPointer() = 0;
llvm::CallInst *emitCallSite();

CallEmission(IRGenFunction &IGF, llvm::Value *selfValue, Callee &&callee)
Expand Down
54 changes: 46 additions & 8 deletions lib/IRGen/Callee.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,31 @@ namespace irgen {

/// A function pointer value.
class FunctionPointer {
/// The actual function pointer.
public:
struct KindTy {
enum class Value {
Function,
AsyncFunctionPointer,
};
static const Value Function = Value::Function;
static const Value AsyncFunctionPointer = Value::AsyncFunctionPointer;
Value value;
KindTy(Value value) : value(value) {}
KindTy(CanSILFunctionType fnType)
: value(fnType->isAsync() ? Value::AsyncFunctionPointer
: Value::Function) {}
friend bool operator==(const KindTy &lhs, const KindTy &rhs) {
return lhs.value == rhs.value;
}
friend bool operator!=(const KindTy &lhs, const KindTy &rhs) {
return !(lhs == rhs);
}
};

private:
KindTy Kind;

/// The actual pointer, either to the function or to its descriptor.
llvm::Value *Value;

PointerAuthInfo AuthInfo;
Expand All @@ -135,25 +159,27 @@ namespace irgen {
/// Construct a FunctionPointer for an arbitrary pointer value.
/// We may add more arguments to this; try to use the other
/// constructors/factories if possible.
explicit FunctionPointer(llvm::Value *value, PointerAuthInfo authInfo,
explicit FunctionPointer(KindTy kind, llvm::Value *value,
PointerAuthInfo authInfo,
const Signature &signature)
: Value(value), AuthInfo(authInfo), Sig(signature) {
: Kind(kind), Value(value), AuthInfo(authInfo), Sig(signature) {
// The function pointer should have function type.
assert(value->getType()->getPointerElementType()->isFunctionTy());
// TODO: maybe assert similarity to signature.getType()?
}

// Temporary only!
explicit FunctionPointer(llvm::Value *value, const Signature &signature)
: FunctionPointer(value, PointerAuthInfo(), signature) {}
explicit FunctionPointer(KindTy kind, llvm::Value *value,
const Signature &signature)
: FunctionPointer(kind, value, PointerAuthInfo(), signature) {}

static FunctionPointer forDirect(IRGenModule &IGM,
llvm::Constant *value,
CanSILFunctionType fnType);

static FunctionPointer forDirect(llvm::Constant *value,
static FunctionPointer forDirect(KindTy kind, llvm::Constant *value,
const Signature &signature) {
return FunctionPointer(value, PointerAuthInfo(), signature);
return FunctionPointer(kind, value, PointerAuthInfo(), signature);
}

static FunctionPointer forExplosionValue(IRGenFunction &IGF,
Expand All @@ -166,8 +192,17 @@ namespace irgen {
return (isa<llvm::Constant>(Value) && AuthInfo.isConstant());
}

KindTy getKind() const { return Kind; }

/// Given that this value is known to have been constructed from a direct
/// function, Return the name of that function.
StringRef getName(IRGenModule &IGM) const;

/// Return the actual function pointer.
llvm::Value *getPointer() const { return Value; }
llvm::Value *getPointer(IRGenFunction &IGF) const;

/// Return the actual function pointer.
llvm::Value *getRawPointer() const { return Value; }

/// Given that this value is known to have been constructed from
/// a direct function, return the function pointer.
Expand Down Expand Up @@ -205,6 +240,9 @@ namespace irgen {

llvm::Value *getExplosionValue(IRGenFunction &IGF,
CanSILFunctionType fnType) const;

/// Form a FunctionPointer whose KindTy is ::Function.
FunctionPointer getAsFunction(IRGenFunction &IGF) const;
};

class Callee {
Expand Down
Loading