mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
206 lines
7.0 KiB
C++
206 lines
7.0 KiB
C++
//===--- GenHasSymbol.cpp - IR Generation for #_hasSymbol queries ---------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2022 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements IR generation for `if #_hasSymbol` condition queries.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTMangler.h"
|
|
#include "swift/AST/PrettyStackTrace.h"
|
|
#include "swift/Basic/Assertions.h"
|
|
#include "swift/IRGen/IRSymbolVisitor.h"
|
|
#include "swift/IRGen/Linking.h"
|
|
#include "swift/SIL/SILFunctionBuilder.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "swift/SIL/SILSymbolVisitor.h"
|
|
#include "clang/AST/DeclObjC.h"
|
|
#include "clang/AST/GlobalDecl.h"
|
|
|
|
#include "GenDecl.h"
|
|
#include "GenericArguments.h"
|
|
#include "IRGenFunction.h"
|
|
#include "IRGenModule.h"
|
|
|
|
using namespace swift;
|
|
using namespace irgen;
|
|
|
|
/// Wrapper for IRGenModule::getAddrOfLLVMVariable() that also handles a few
|
|
/// additional types of entities that the main utility cannot.
|
|
static llvm::Constant *getAddrOfLLVMVariable(IRGenModule &IGM,
|
|
LinkEntity entity) {
|
|
if (entity.isTypeMetadataAccessFunction()) {
|
|
auto type = entity.getType();
|
|
auto nominal = type->getAnyNominal();
|
|
assert(nominal);
|
|
|
|
if (nominal->isGenericContext()) {
|
|
GenericArguments genericArgs;
|
|
genericArgs.collectTypes(IGM, nominal);
|
|
|
|
return IGM.getAddrOfGenericTypeMetadataAccessFunction(nominal,
|
|
genericArgs.Types,
|
|
NotForDefinition);
|
|
} else {
|
|
return IGM.getAddrOfTypeMetadataAccessFunction(type,
|
|
NotForDefinition);
|
|
}
|
|
}
|
|
if (entity.isDispatchThunk())
|
|
return IGM.getAddrOfDispatchThunk(entity.getSILDeclRef(), NotForDefinition);
|
|
|
|
if (entity.isOpaqueTypeDescriptorAccessor()) {
|
|
OpaqueTypeDecl *decl =
|
|
const_cast<OpaqueTypeDecl *>(cast<OpaqueTypeDecl>(entity.getDecl()));
|
|
bool isImplementation = entity.isOpaqueTypeDescriptorAccessorImpl();
|
|
return IGM
|
|
.getAddrOfOpaqueTypeDescriptorAccessFunction(decl, NotForDefinition,
|
|
isImplementation)
|
|
.getDirectPointer();
|
|
}
|
|
|
|
// FIXME: Look up addr of the replaceable function (has "TI" mangling suffix)
|
|
if (entity.isDynamicallyReplaceableFunctionImpl())
|
|
return nullptr;
|
|
|
|
return IGM.getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
|
|
}
|
|
|
|
class HasSymbolIRGenVisitor : public IRSymbolVisitor {
|
|
IRGenModule &IGM;
|
|
llvm::SmallVector<llvm::Constant *, 4> &Addrs;
|
|
|
|
void addFunction(SILFunction *fn) {
|
|
Addrs.emplace_back(IGM.getAddrOfSILFunction(fn, NotForDefinition));
|
|
}
|
|
|
|
void addFunction(StringRef name) {
|
|
SILFunction *silFn = IGM.getSILModule().lookUpFunction(name);
|
|
// Definitions for each SIL function should have been emitted by SILGen.
|
|
assert(silFn && "missing SIL function?");
|
|
if (silFn)
|
|
addFunction(silFn);
|
|
}
|
|
|
|
public:
|
|
HasSymbolIRGenVisitor(IRGenModule &IGM,
|
|
llvm::SmallVector<llvm::Constant *, 4> &Addrs)
|
|
: IGM{IGM}, Addrs{Addrs} {};
|
|
|
|
void addFunction(SILDeclRef declRef) override {
|
|
addFunction(declRef.mangle());
|
|
}
|
|
|
|
void addFunction(StringRef name, SILDeclRef declRef) override {
|
|
addFunction(name);
|
|
}
|
|
|
|
void addGlobalVar(VarDecl *VD) override {
|
|
// FIXME: Handle global vars
|
|
llvm::report_fatal_error("unhandled global var");
|
|
}
|
|
|
|
void addLinkEntity(LinkEntity entity) override {
|
|
// Skip property descriptors for static properties, which were only
|
|
// introduced with SE-0438 and are therefore not present in all libraries.
|
|
if (entity.isPropertyDescriptor()) {
|
|
if (entity.getAbstractStorageDecl()->isStatic())
|
|
return;
|
|
}
|
|
|
|
if (entity.hasSILFunction()) {
|
|
addFunction(entity.getSILFunction());
|
|
return;
|
|
}
|
|
|
|
auto constant = getAddrOfLLVMVariable(IGM, entity);
|
|
if (constant) {
|
|
auto global = cast<llvm::GlobalValue>(constant);
|
|
Addrs.emplace_back(global);
|
|
}
|
|
}
|
|
|
|
void addProtocolWitnessThunk(RootProtocolConformance *C,
|
|
ValueDecl *requirementDecl) override {
|
|
// FIXME: Handle protocol witness thunks
|
|
llvm::report_fatal_error("unhandled protocol witness thunk");
|
|
}
|
|
};
|
|
|
|
static llvm::Constant *
|
|
getAddrOfLLVMVariableForClangDecl(IRGenModule &IGM, ValueDecl *decl,
|
|
const clang::Decl *clangDecl) {
|
|
if (isa<clang::FunctionDecl>(clangDecl)) {
|
|
SILFunction *silFn =
|
|
IGM.getSILModule().lookUpFunction(SILDeclRef(decl).asForeign());
|
|
assert(silFn && "missing SIL function?");
|
|
return silFn ? IGM.getAddrOfSILFunction(silFn, NotForDefinition) : nullptr;
|
|
}
|
|
|
|
if (isa<clang::ObjCInterfaceDecl>(clangDecl))
|
|
return IGM.getAddrOfObjCClass(cast<ClassDecl>(decl), NotForDefinition);
|
|
|
|
llvm::report_fatal_error("Unexpected clang decl kind");
|
|
}
|
|
|
|
static void
|
|
getSymbolAddrsForDecl(IRGenModule &IGM, ValueDecl *decl,
|
|
llvm::SmallVector<llvm::Constant *, 4> &addrs) {
|
|
if (auto *clangDecl = decl->getClangDecl()) {
|
|
if (auto *addr = getAddrOfLLVMVariableForClangDecl(IGM, decl, clangDecl))
|
|
addrs.push_back(addr);
|
|
return;
|
|
}
|
|
|
|
SILSymbolVisitorOptions opts;
|
|
opts.VisitMembers = false;
|
|
auto silCtx = SILSymbolVisitorContext(IGM.getSwiftModule(), opts);
|
|
auto linkInfo = UniversalLinkageInfo(IGM);
|
|
auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx);
|
|
HasSymbolIRGenVisitor(IGM, addrs).visit(decl, symbolVisitorCtx);
|
|
}
|
|
|
|
llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) {
|
|
|
|
PrettyStackTraceDecl trace("emitting #_hasSymbol query for", decl);
|
|
Mangle::ASTMangler mangler(Context);
|
|
|
|
auto func = cast<llvm::Function>(getOrCreateHelperFunction(
|
|
mangler.mangleHasSymbolQuery(decl), Int1Ty, {},
|
|
[decl, this](IRGenFunction &IGF) {
|
|
auto &Builder = IGF.Builder;
|
|
llvm::SmallVector<llvm::Constant *, 4> addrs;
|
|
getSymbolAddrsForDecl(*this, decl, addrs);
|
|
|
|
llvm::Value *ret = nullptr;
|
|
for (llvm::Constant *addr : addrs) {
|
|
assert(cast<llvm::GlobalValue>(addr)->hasExternalWeakLinkage());
|
|
|
|
auto isNonNull = IGF.Builder.CreateIsNotNull(addr);
|
|
ret = (ret) ? IGF.Builder.CreateAnd(ret, isNonNull) : isNonNull;
|
|
}
|
|
|
|
if (ret) {
|
|
Builder.CreateRet(ret);
|
|
} else {
|
|
// There were no addresses produced by the visitor, return true.
|
|
Builder.CreateRet(llvm::ConstantInt::get(Int1Ty, 1));
|
|
}
|
|
},
|
|
/*IsNoInline*/ false));
|
|
|
|
func->setDoesNotThrow();
|
|
func->setCallingConv(DefaultCC);
|
|
func->setOnlyReadsMemory();
|
|
|
|
return func;
|
|
}
|