Skip to content

[interop][SwiftToCxx] Gather initial struct layout information and em… #59119

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
merged 2 commits into from
Jun 3, 2022
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
53 changes: 53 additions & 0 deletions include/swift/IRGen/IRABIDetailsProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//===--- IRABIDetailsProvider.h - Get ABI details for decls -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 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
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_IRGEN_IRABIDETAILSPROVIDER_H
#define SWIFT_IRGEN_IRABIDETAILSPROVIDER_H

#include "llvm/ADT/Optional.h"
#include <stdint.h>
#include <utility>

namespace swift {

class IRGenOptions;
class ModuleDecl;
class NominalTypeDecl;

class IRABIDetailsProviderImpl;

/// Provides access to the IRGen-based queries that can be performed on
/// declarations to get their various ABI details.
class IRABIDetailsProvider {
public:
IRABIDetailsProvider(ModuleDecl &mod, const IRGenOptions &opts);
~IRABIDetailsProvider();

using SizeType = uint64_t;

struct SizeAndAlignment {
SizeType size;
SizeType alignment;
};

/// Returns the size and alignment for the given type, or \c None if the type
/// is not a fixed layout type.
llvm::Optional<SizeAndAlignment>
getTypeSizeAlignment(const NominalTypeDecl *TD);

private:
std::unique_ptr<IRABIDetailsProviderImpl> impl;
};

} // namespace swift

#endif
32 changes: 17 additions & 15 deletions include/swift/PrintAsClang/PrintAsClang.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,24 @@
#include "swift/AST/Identifier.h"

namespace swift {
class ModuleDecl;
class ValueDecl;
class IRGenOptions;
class ModuleDecl;
class ValueDecl;

/// Print the exposed declarations in a module into a Clang header.
///
/// The Objective-C compatible declarations are printed into a block that
/// ensures that those declarations are only usable when the header is
/// compiled in Objective-C mode.
/// The C++ compatible declarations are printed into a block that ensures
/// that those declarations are only usable when the header is compiled in
/// C++ mode.
///
/// Returns true on error.
bool printAsClangHeader(raw_ostream &out, ModuleDecl *M,
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader);
/// Print the exposed declarations in a module into a Clang header.
///
/// The Objective-C compatible declarations are printed into a block that
/// ensures that those declarations are only usable when the header is
/// compiled in Objective-C mode.
/// The C++ compatible declarations are printed into a block that ensures
/// that those declarations are only usable when the header is compiled in
/// C++ mode.
///
/// Returns true on error.
bool printAsClangHeader(raw_ostream &out, ModuleDecl *M,
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader,
const IRGenOptions &irGenOpts);
}

#endif
7 changes: 4 additions & 3 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,14 @@ static bool writeSIL(SILModule &SM, const PrimarySpecificPaths &PSPs,
/// \see swift::printAsClangHeader
static bool printAsClangHeaderIfNeeded(StringRef outputPath, ModuleDecl *M,
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader) {
bool ExposePublicDeclsInClangHeader,
const IRGenOptions &irGenOpts) {
if (outputPath.empty())
return false;
return withOutputFile(
M->getDiags(), outputPath, [&](raw_ostream &out) -> bool {
return printAsClangHeader(out, M, bridgingHeader,
ExposePublicDeclsInClangHeader);
ExposePublicDeclsInClangHeader, irGenOpts);
});
}

Expand Down Expand Up @@ -859,7 +860,7 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
hadAnyError |= printAsClangHeaderIfNeeded(
Invocation.getClangHeaderOutputPathForAtMostOnePrimary(),
Instance.getMainModule(), BridgingHeaderPathForPrint,
opts.ExposePublicDeclsInClangHeader);
opts.ExposePublicDeclsInClangHeader, Invocation.getIRGenOptions());
}

// Only want the header if there's been any errors, ie. there's not much
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ add_swift_host_library(swiftIRGen STATIC
GenTuple.cpp
GenType.cpp
GenValueWitness.cpp
IRABIDetailsProvider.cpp
IRGen.cpp
IRGenDebugInfo.cpp
IRGenFunction.cpp
Expand Down
67 changes: 67 additions & 0 deletions lib/IRGen/IRABIDetailsProvider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===--- IRABIDetailsProvider.cpp - Get ABI details for decls ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 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
//
//===----------------------------------------------------------------------===//

#include "swift/IRGen/IRABIDetailsProvider.h"
#include "FixedTypeInfo.h"
#include "GenType.h"
#include "IRGen.h"
#include "IRGenModule.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/Types.h"
#include "swift/SIL/SILModule.h"

using namespace swift;
using namespace irgen;

namespace swift {

class IRABIDetailsProviderImpl {
public:
IRABIDetailsProviderImpl(ModuleDecl &mod, const IRGenOptions &opts)
: typeConverter(mod),
silMod(SILModule::createEmptyModule(&mod, typeConverter, silOpts)),
IRGen(opts, *silMod), IGM(IRGen, IRGen.createTargetMachine()) {}

llvm::Optional<IRABIDetailsProvider::SizeAndAlignment>
getTypeSizeAlignment(const NominalTypeDecl *TD) {
auto *TI = &IGM.getTypeInfoForUnlowered(TD->getDeclaredTypeInContext());
auto *fixedTI = dyn_cast<FixedTypeInfo>(TI);
if (!fixedTI)
return None;
return IRABIDetailsProvider::SizeAndAlignment{
fixedTI->getFixedSize().getValue(),
fixedTI->getFixedAlignment().getValue()};
}

private:
Lowering::TypeConverter typeConverter;
// Default silOptions are sufficient, as we don't need to generated SIL.
SILOptions silOpts;
std::unique_ptr<SILModule> silMod;
IRGenerator IRGen;
IRGenModule IGM;
};

} // namespace swift

IRABIDetailsProvider::IRABIDetailsProvider(ModuleDecl &mod,
const IRGenOptions &opts)
: impl(std::make_unique<IRABIDetailsProviderImpl>(mod, opts)) {}

IRABIDetailsProvider::~IRABIDetailsProvider() {}

llvm::Optional<IRABIDetailsProvider::SizeAndAlignment>
IRABIDetailsProvider::getTypeSizeAlignment(const NominalTypeDecl *TD) {
return impl->getTypeSizeAlignment(TD);
}
6 changes: 4 additions & 2 deletions lib/PrintAsClang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ add_swift_host_library(swiftPrintAsClang STATIC
PrimitiveTypeMapping.cpp
PrintAsClang.cpp
PrintClangFunction.cpp
PrintClangValueType.cpp)
PrintClangValueType.cpp
SwiftToClangInteropContext.cpp)
target_link_libraries(swiftPrintAsClang PRIVATE
swiftAST
swiftClangImporter
swiftFrontend
swiftIDE)
swiftIDE
swiftIRGen)

set_swift_llvm_is_available(swiftPrintAsClang)
2 changes: 1 addition & 1 deletion lib/PrintAsClang/DeclAndTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ class DeclAndTypePrinter::Implementation
if (outputLang != OutputLanguageMode::Cxx)
return;
// FIXME: Print struct's availability.
ClangValueTypePrinter printer(os);
ClangValueTypePrinter printer(os, owningPrinter.interopContext);
printer.printStructDecl(SD);
}

Expand Down
11 changes: 7 additions & 4 deletions lib/PrintAsClang/DeclAndTypePrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace swift {

class PrimitiveTypeMapping;
class ValueDecl;
class SwiftToClangInteropContext;

/// Responsible for printing a Swift Decl or Type in Objective-C, to be
/// included in a Swift module's ObjC compatibility header.
Expand All @@ -43,6 +44,7 @@ class DeclAndTypePrinter {
raw_ostream &prologueOS;
const DelayedMemberSet &delayedMembers;
PrimitiveTypeMapping &typeMapping;
SwiftToClangInteropContext &interopContext;
AccessLevel minRequiredAccess;
OutputLanguageMode outputLang;

Expand All @@ -56,11 +58,12 @@ class DeclAndTypePrinter {
public:
DeclAndTypePrinter(ModuleDecl &mod, raw_ostream &out, raw_ostream &prologueOS,
DelayedMemberSet &delayed,
PrimitiveTypeMapping &typeMapping, AccessLevel access,
OutputLanguageMode outputLang)
PrimitiveTypeMapping &typeMapping,
SwiftToClangInteropContext &interopContext,
AccessLevel access, OutputLanguageMode outputLang)
: M(mod), os(out), prologueOS(prologueOS), delayedMembers(delayed),
typeMapping(typeMapping), minRequiredAccess(access),
outputLang(outputLang) {}
typeMapping(typeMapping), interopContext(interopContext),
minRequiredAccess(access), outputLang(outputLang) {}

/// Returns true if \p VD should be included in a compatibility header for
/// the options the printer was constructed with.
Expand Down
22 changes: 11 additions & 11 deletions lib/PrintAsClang/ModuleContentsWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,11 @@ class ModuleWriter {
public:
ModuleWriter(raw_ostream &os, raw_ostream &prologueOS,
llvm::SmallPtrSetImpl<ImportModuleTy> &imports, ModuleDecl &mod,
AccessLevel access, OutputLanguageMode outputLang)
SwiftToClangInteropContext &interopContext, AccessLevel access,
OutputLanguageMode outputLang)
: os(os), imports(imports), M(mod),
printer(M, os, prologueOS, delayedMembers, typeMapping, access,
outputLang),
printer(M, os, prologueOS, delayedMembers, typeMapping, interopContext,
access, outputLang),
outputLangMode(outputLang) {}

/// Returns true if we added the decl's module to the import set, false if
Expand Down Expand Up @@ -638,26 +639,25 @@ static AccessLevel getRequiredAccess(const ModuleDecl &M) {
return M.isExternallyConsumed() ? AccessLevel::Public : AccessLevel::Internal;
}

void
swift::printModuleContentsAsObjC(raw_ostream &os,
llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
ModuleDecl &M) {
void swift::printModuleContentsAsObjC(
raw_ostream &os, llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
ModuleDecl &M, SwiftToClangInteropContext &interopContext) {
llvm::raw_null_ostream prologueOS;
ModuleWriter(os, prologueOS, imports, M, getRequiredAccess(M),
ModuleWriter(os, prologueOS, imports, M, interopContext, getRequiredAccess(M),
OutputLanguageMode::ObjC)
.write();
}

void swift::printModuleContentsAsCxx(
raw_ostream &os, llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
ModuleDecl &M) {
ModuleDecl &M, SwiftToClangInteropContext &interopContext) {
std::string moduleContentsBuf;
llvm::raw_string_ostream moduleOS{moduleContentsBuf};
std::string modulePrologueBuf;
llvm::raw_string_ostream prologueOS{modulePrologueBuf};

ModuleWriter(moduleOS, prologueOS, imports, M, getRequiredAccess(M),
OutputLanguageMode::Cxx)
ModuleWriter(moduleOS, prologueOS, imports, M, interopContext,
getRequiredAccess(M), OutputLanguageMode::Cxx)
.write();

// FIXME: refactor.
Expand Down
7 changes: 5 additions & 2 deletions lib/PrintAsClang/ModuleContentsWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,23 @@ namespace clang {

namespace swift {
class ModuleDecl;
class SwiftToClangInteropContext;

using ImportModuleTy = PointerUnion<ModuleDecl*, const clang::Module*>;

/// Prints the declarations of \p M to \p os and collecting imports in
/// \p imports along the way.
void printModuleContentsAsObjC(raw_ostream &os,
llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
ModuleDecl &M);
ModuleDecl &M,
SwiftToClangInteropContext &interopContext);

/// Prints the declarations of \p M to \p os in C++ language mode and collects
/// imports in \p imports along the way.
void printModuleContentsAsCxx(raw_ostream &os,
llvm::SmallPtrSetImpl<ImportModuleTy> &imports,
ModuleDecl &M);
ModuleDecl &M,
SwiftToClangInteropContext &interopContext);

} // end namespace swift

Expand Down
16 changes: 11 additions & 5 deletions lib/PrintAsClang/PrintAsClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "swift/PrintAsClang/PrintAsClang.h"

#include "ModuleContentsWriter.h"
#include "SwiftToClangInteropContext.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h"
Expand Down Expand Up @@ -458,23 +459,28 @@ static std::string computeMacroGuard(const ModuleDecl *M) {
return (llvm::Twine(M->getNameStr().upper()) + "_SWIFT_H").str();
}

static std::string getModuleContentsCxxString(ModuleDecl &M) {
static std::string
getModuleContentsCxxString(ModuleDecl &M,
SwiftToClangInteropContext &interopContext) {
SmallPtrSet<ImportModuleTy, 8> imports;
std::string moduleContentsBuf;
llvm::raw_string_ostream moduleContents{moduleContentsBuf};
printModuleContentsAsCxx(moduleContents, imports, M);
printModuleContentsAsCxx(moduleContents, imports, M, interopContext);
return moduleContents.str();
}

bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader) {
bool ExposePublicDeclsInClangHeader,
const IRGenOptions &irGenOpts) {
llvm::PrettyStackTraceString trace("While generating Clang header");

SwiftToClangInteropContext interopContext(*M, irGenOpts);

SmallPtrSet<ImportModuleTy, 8> imports;
std::string objcModuleContentsBuf;
llvm::raw_string_ostream objcModuleContents{objcModuleContentsBuf};
printModuleContentsAsObjC(objcModuleContents, imports, *M);
printModuleContentsAsObjC(objcModuleContents, imports, *M, interopContext);
writePrologue(os, M->getASTContext(), computeMacroGuard(M));
emitObjCConditional(os,
[&] { writeImports(os, imports, *M, bridgingHeader); });
Expand All @@ -483,7 +489,7 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
emitCxxConditional(os, [&] {
// FIXME: Expose Swift with @expose by default.
if (ExposePublicDeclsInClangHeader) {
os << getModuleContentsCxxString(*M);
os << getModuleContentsCxxString(*M, interopContext);
}
});
writeEpilogue(os);
Expand Down
Loading