mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[interop][SwiftToCxx] pass / return Swift struct values between C/C++ and Swift
This commit is contained in:
@@ -13,13 +13,17 @@
|
||||
#ifndef SWIFT_IRGEN_IRABIDETAILSPROVIDER_H
|
||||
#define SWIFT_IRGEN_IRABIDETAILSPROVIDER_H
|
||||
|
||||
#include "swift/AST/Type.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace swift {
|
||||
|
||||
class ASTContext;
|
||||
class IRGenOptions;
|
||||
class ModuleDecl;
|
||||
class NominalTypeDecl;
|
||||
@@ -45,6 +49,24 @@ public:
|
||||
llvm::Optional<SizeAndAlignment>
|
||||
getTypeSizeAlignment(const NominalTypeDecl *TD);
|
||||
|
||||
/// Returns true if the given type should be passed indirectly into a swiftcc
|
||||
/// function.
|
||||
bool shouldPassIndirectly(Type t);
|
||||
|
||||
/// Returns true if the given type should be returned indirectly from a
|
||||
/// swiftcc function.
|
||||
bool shouldReturnIndirectly(Type t);
|
||||
|
||||
/// Enumerates all of the members of the underlying record in terms of their
|
||||
/// primitive types that needs to be stored in a Clang/LLVM record when this
|
||||
/// type is passed or returned directly to/from swiftcc function.
|
||||
///
|
||||
/// Returns true if an error occurred when a particular member can't be
|
||||
/// represented with an AST type.
|
||||
bool enumerateDirectPassingRecordMembers(
|
||||
Type t, llvm::function_ref<void(clang::CharUnits, clang::CharUnits, Type)>
|
||||
callback);
|
||||
|
||||
private:
|
||||
std::unique_ptr<IRABIDetailsProviderImpl> impl;
|
||||
};
|
||||
|
||||
@@ -15,15 +15,45 @@
|
||||
#include "GenType.h"
|
||||
#include "IRGen.h"
|
||||
#include "IRGenModule.h"
|
||||
#include "NativeConventionSchema.h"
|
||||
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/IRGenOptions.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "clang/CodeGen/ModuleBuilder.h"
|
||||
#include "clang/CodeGen/SwiftCallingConv.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace irgen;
|
||||
|
||||
static Optional<Type> getPrimitiveTypeFromLLVMType(ASTContext &ctx,
|
||||
const llvm::Type *type) {
|
||||
if (const auto *intType = dyn_cast<llvm::IntegerType>(type)) {
|
||||
switch (intType->getBitWidth()) {
|
||||
case 8:
|
||||
return ctx.getUInt8Type();
|
||||
case 16:
|
||||
return ctx.getUInt16Type();
|
||||
case 32:
|
||||
return ctx.getUInt32Type();
|
||||
case 64:
|
||||
return ctx.getUInt64Type();
|
||||
default:
|
||||
return None;
|
||||
}
|
||||
} else if (type->isFloatTy()) {
|
||||
return ctx.getFloatType();
|
||||
} else if (type->isDoubleTy()) {
|
||||
return ctx.getDoubleType();
|
||||
} else if (type->isPointerTy()) {
|
||||
return ctx.getOpaquePointerType();
|
||||
}
|
||||
// FIXME: Handle vector type.
|
||||
return None;
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
|
||||
class IRABIDetailsProviderImpl {
|
||||
@@ -44,6 +74,39 @@ public:
|
||||
fixedTI->getFixedAlignment().getValue()};
|
||||
}
|
||||
|
||||
bool shouldPassIndirectly(Type type) {
|
||||
auto *TI = &IGM.getTypeInfoForUnlowered(type);
|
||||
NativeConventionSchema schema(IGM, TI, /*isResult=*/false);
|
||||
return schema.requiresIndirect();
|
||||
}
|
||||
|
||||
bool shouldReturnIndirectly(Type type) {
|
||||
if (type->isVoid())
|
||||
return false;
|
||||
auto *TI = &IGM.getTypeInfoForUnlowered(type);
|
||||
NativeConventionSchema schema(IGM, TI, /*isResult=*/true);
|
||||
return schema.requiresIndirect();
|
||||
}
|
||||
|
||||
bool enumerateDirectPassingRecordMembers(
|
||||
Type t, llvm::function_ref<void(clang::CharUnits, clang::CharUnits, Type)>
|
||||
callback) {
|
||||
auto *TI = &IGM.getTypeInfoForUnlowered(t);
|
||||
NativeConventionSchema schema(IGM, TI, /*isResult=*/false);
|
||||
bool hasError = false;
|
||||
schema.enumerateComponents(
|
||||
[&](clang::CharUnits offset, clang::CharUnits end, llvm::Type *type) {
|
||||
auto primitiveType = getPrimitiveTypeFromLLVMType(
|
||||
IGM.getSwiftModule()->getASTContext(), type);
|
||||
if (!primitiveType) {
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
callback(offset, end, *primitiveType);
|
||||
});
|
||||
return hasError;
|
||||
}
|
||||
|
||||
private:
|
||||
Lowering::TypeConverter typeConverter;
|
||||
// Default silOptions are sufficient, as we don't need to generated SIL.
|
||||
@@ -65,3 +128,17 @@ llvm::Optional<IRABIDetailsProvider::SizeAndAlignment>
|
||||
IRABIDetailsProvider::getTypeSizeAlignment(const NominalTypeDecl *TD) {
|
||||
return impl->getTypeSizeAlignment(TD);
|
||||
}
|
||||
|
||||
bool IRABIDetailsProvider::shouldPassIndirectly(Type t) {
|
||||
return impl->shouldPassIndirectly(t);
|
||||
}
|
||||
|
||||
bool IRABIDetailsProvider::shouldReturnIndirectly(Type t) {
|
||||
return impl->shouldReturnIndirectly(t);
|
||||
}
|
||||
|
||||
bool IRABIDetailsProvider::enumerateDirectPassingRecordMembers(
|
||||
Type t, llvm::function_ref<void(clang::CharUnits, clang::CharUnits, Type)>
|
||||
callback) {
|
||||
return impl->enumerateDirectPassingRecordMembers(t, callback);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ClangSyntaxPrinter.h"
|
||||
#include "swift/AST/Module.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace cxx_synthesis;
|
||||
@@ -43,6 +44,10 @@ void ClangSyntaxPrinter::printIdentifier(StringRef name) {
|
||||
os << '_';
|
||||
}
|
||||
|
||||
void ClangSyntaxPrinter::printModuleNameCPrefix(const ModuleDecl &mod) {
|
||||
os << mod.getName().str() << '_';
|
||||
}
|
||||
|
||||
/// Print a C++ namespace declaration with the give name and body.
|
||||
void ClangSyntaxPrinter::printNamespace(
|
||||
llvm::function_ref<void(raw_ostream &OS)> namePrinter,
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
class ModuleDecl;
|
||||
|
||||
namespace cxx_synthesis {
|
||||
|
||||
/// Return the name of the implementation namespace that is used to hide
|
||||
@@ -37,6 +39,10 @@ public:
|
||||
/// trailing underscore.
|
||||
void printIdentifier(StringRef name);
|
||||
|
||||
/// Print the C-style prefix for the given module name, that's used for
|
||||
/// C type names inside the module.
|
||||
void printModuleNameCPrefix(const ModuleDecl &mod);
|
||||
|
||||
/// Print a C++ namespace declaration with the give name and body.
|
||||
void
|
||||
printNamespace(llvm::function_ref<void(raw_ostream &OS)> namePrinter,
|
||||
|
||||
@@ -332,7 +332,9 @@ private:
|
||||
if (outputLang != OutputLanguageMode::Cxx)
|
||||
return;
|
||||
// FIXME: Print struct's availability.
|
||||
ClangValueTypePrinter printer(os, owningPrinter.interopContext);
|
||||
ClangValueTypePrinter printer(os, owningPrinter.prologueOS,
|
||||
owningPrinter.typeMapping,
|
||||
owningPrinter.interopContext);
|
||||
printer.printStructDecl(SD);
|
||||
}
|
||||
|
||||
@@ -834,7 +836,9 @@ private:
|
||||
|
||||
os << "SWIFT_EXTERN ";
|
||||
|
||||
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.typeMapping);
|
||||
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS,
|
||||
owningPrinter.typeMapping,
|
||||
owningPrinter.interopContext);
|
||||
funcPrinter.printFunctionSignature(
|
||||
FD, funcABI.getSymbolName(), resultTy,
|
||||
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto);
|
||||
@@ -873,7 +877,9 @@ private:
|
||||
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
|
||||
|
||||
os << "inline ";
|
||||
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.typeMapping);
|
||||
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS,
|
||||
owningPrinter.typeMapping,
|
||||
owningPrinter.interopContext);
|
||||
funcPrinter.printFunctionSignature(
|
||||
FD, FD->getName().getBaseIdentifier().get(), resultTy,
|
||||
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CxxInlineThunk);
|
||||
@@ -882,27 +888,8 @@ private:
|
||||
printFunctionClangAttributes(FD, funcTy);
|
||||
printAvailability(FD);
|
||||
os << " {\n";
|
||||
os << " return " << cxx_synthesis::getCxxImplNamespaceName()
|
||||
<< "::" << funcABI.getSymbolName() << '(';
|
||||
|
||||
auto params = FD->getParameters();
|
||||
if (params->size()) {
|
||||
size_t index = 1;
|
||||
interleaveComma(*params, os, [&](const ParamDecl *param) {
|
||||
if (param->isInOut()) {
|
||||
os << "&";
|
||||
}
|
||||
|
||||
if (param->hasName()) {
|
||||
ClangSyntaxPrinter(os).printIdentifier(param->getName().str());
|
||||
} else {
|
||||
os << "_" << index;
|
||||
}
|
||||
++index;
|
||||
});
|
||||
}
|
||||
|
||||
os << ");\n";
|
||||
funcPrinter.printCxxThunkBody(funcABI.getSymbolName(), resultTy,
|
||||
FD->getParameters());
|
||||
os << "}\n";
|
||||
}
|
||||
|
||||
@@ -1112,8 +1099,11 @@ private:
|
||||
if (outputLang == OutputLanguageMode::Cxx) {
|
||||
// Emit the underlying C signature that matches the Swift ABI
|
||||
// in the generated C++ implementation prologue for the module.
|
||||
auto funcABI = getModuleProloguePrinter()
|
||||
std::string cFuncDecl;
|
||||
llvm::raw_string_ostream cFuncPrologueOS(cFuncDecl);
|
||||
auto funcABI = Implementation(cFuncPrologueOS, owningPrinter, outputLang)
|
||||
.printSwiftABIFunctionSignatureAsCxxFunction(FD);
|
||||
owningPrinter.prologueOS << cFuncPrologueOS.str();
|
||||
printAbstractFunctionAsCxxFunctionThunk(FD, funcABI);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -265,6 +265,9 @@ public:
|
||||
forwardDeclare(ED);
|
||||
} else if (isa<AbstractTypeParamDecl>(TD)) {
|
||||
llvm_unreachable("should not see type params here");
|
||||
} else if (isa<StructDecl>(TD)) {
|
||||
// FIXME: add support here.
|
||||
return;
|
||||
} else {
|
||||
assert(false && "unknown local type decl");
|
||||
}
|
||||
@@ -668,6 +671,7 @@ void swift::printModuleContentsAsCxx(
|
||||
M.ValueDecl::getName().print(os);
|
||||
os << " {\n";
|
||||
os << "namespace " << cxx_synthesis::getCxxImplNamespaceName() << " {\n";
|
||||
os << "extern \"C\" {\n";
|
||||
os << "#endif\n\n";
|
||||
|
||||
os << prologueOS.str();
|
||||
@@ -675,6 +679,7 @@ void swift::printModuleContentsAsCxx(
|
||||
os << "\n#ifdef __cplusplus\n";
|
||||
os << "}\n";
|
||||
os << "}\n";
|
||||
os << "}\n";
|
||||
}
|
||||
|
||||
// Construct a C++ namespace for the module.
|
||||
|
||||
@@ -89,12 +89,14 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
|
||||
[&] {
|
||||
out << "#include <cstdint>\n"
|
||||
"#include <cstddef>\n"
|
||||
"#include <cstdbool>\n";
|
||||
"#include <cstdbool>\n"
|
||||
"#include <cstring>\n";
|
||||
},
|
||||
[&] {
|
||||
out << "#include <stdint.h>\n"
|
||||
"#include <stddef.h>\n"
|
||||
"#include <stdbool.h>\n";
|
||||
"#include <stdbool.h>\n"
|
||||
"#include <string.h>\n";
|
||||
});
|
||||
out << "\n"
|
||||
"#if !defined(SWIFT_TYPEDEFS)\n"
|
||||
@@ -301,6 +303,7 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
|
||||
out << "#endif\n";
|
||||
};
|
||||
emitMacro("SWIFT_CALL", "__attribute__((swiftcall))");
|
||||
emitMacro("SWIFT_INDIRECT_RESULT", "__attribute__((swift_indirect_result))");
|
||||
// SWIFT_NOEXCEPT applies 'noexcept' in C++ mode only.
|
||||
emitCxxConditional(
|
||||
out, [&] { emitMacro("SWIFT_NOEXCEPT", "noexcept"); },
|
||||
|
||||
@@ -15,17 +15,42 @@
|
||||
#include "DeclAndTypePrinter.h"
|
||||
#include "OutputLanguageMode.h"
|
||||
#include "PrimitiveTypeMapping.h"
|
||||
#include "PrintClangValueType.h"
|
||||
#include "SwiftToClangInteropContext.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ParameterList.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/TypeVisitor.h"
|
||||
#include "swift/ClangImporter/ClangImporter.h"
|
||||
#include "swift/IRGen/IRABIDetailsProvider.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
namespace {
|
||||
|
||||
enum class FunctionSignatureTypeUse { ParamType, ReturnType };
|
||||
|
||||
Optional<PrimitiveTypeMapping::ClangTypeInfo>
|
||||
getKnownTypeInfo(const TypeDecl *typeDecl, PrimitiveTypeMapping &typeMapping,
|
||||
OutputLanguageMode languageMode) {
|
||||
return languageMode == OutputLanguageMode::Cxx
|
||||
? typeMapping.getKnownCxxTypeInfo(typeDecl)
|
||||
: typeMapping.getKnownCTypeInfo(typeDecl);
|
||||
}
|
||||
|
||||
bool isKnownCxxType(Type t, PrimitiveTypeMapping &typeMapping) {
|
||||
const TypeDecl *typeDecl;
|
||||
if (auto *typeAliasType = dyn_cast<TypeAliasType>(t.getPointer()))
|
||||
typeDecl = typeAliasType->getDecl();
|
||||
else if (auto *structDecl = t->getStructOrBoundGenericStruct())
|
||||
typeDecl = structDecl;
|
||||
else
|
||||
return false;
|
||||
return getKnownTypeInfo(typeDecl, typeMapping, OutputLanguageMode::Cxx) !=
|
||||
None;
|
||||
}
|
||||
|
||||
// Prints types in the C function signature that corresponds to the
|
||||
// native Swift function/method.
|
||||
class CFunctionSignatureTypePrinter
|
||||
@@ -33,17 +58,19 @@ class CFunctionSignatureTypePrinter
|
||||
Optional<OptionalTypeKind>>,
|
||||
private ClangSyntaxPrinter {
|
||||
public:
|
||||
CFunctionSignatureTypePrinter(raw_ostream &os,
|
||||
CFunctionSignatureTypePrinter(raw_ostream &os, raw_ostream &cPrologueOS,
|
||||
PrimitiveTypeMapping &typeMapping,
|
||||
OutputLanguageMode languageMode)
|
||||
: ClangSyntaxPrinter(os), typeMapping(typeMapping),
|
||||
languageMode(languageMode) {}
|
||||
OutputLanguageMode languageMode,
|
||||
SwiftToClangInteropContext &interopContext,
|
||||
FunctionSignatureTypeUse typeUseKind =
|
||||
FunctionSignatureTypeUse::ParamType)
|
||||
: ClangSyntaxPrinter(os), cPrologueOS(cPrologueOS),
|
||||
typeMapping(typeMapping), interopContext(interopContext),
|
||||
languageMode(languageMode), typeUseKind(typeUseKind) {}
|
||||
|
||||
bool printIfKnownSimpleType(const TypeDecl *typeDecl,
|
||||
Optional<OptionalTypeKind> optionalKind) {
|
||||
auto knownTypeInfo = languageMode == OutputLanguageMode::Cxx
|
||||
? typeMapping.getKnownCxxTypeInfo(typeDecl)
|
||||
: typeMapping.getKnownCTypeInfo(typeDecl);
|
||||
auto knownTypeInfo = getKnownTypeInfo(typeDecl, typeMapping, languageMode);
|
||||
if (!knownTypeInfo)
|
||||
return false;
|
||||
os << knownTypeInfo->name;
|
||||
@@ -81,7 +108,19 @@ public:
|
||||
// Handle known type names.
|
||||
if (printIfKnownSimpleType(SD, optionalKind))
|
||||
return;
|
||||
// FIXME: Handle struct types.
|
||||
// FIXME: Handle optional structures.
|
||||
if (typeUseKind == FunctionSignatureTypeUse::ParamType) {
|
||||
if (languageMode != OutputLanguageMode::Cxx &&
|
||||
interopContext.getIrABIDetails().shouldPassIndirectly(ST)) {
|
||||
// FIXME: it would be nice to print out the C struct type here.
|
||||
os << "const void * _Nonnull";
|
||||
} else {
|
||||
ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext)
|
||||
.printValueTypeParameterType(SD, languageMode);
|
||||
}
|
||||
} else
|
||||
ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext)
|
||||
.printValueTypeReturnType(SD, languageMode);
|
||||
}
|
||||
|
||||
void visitPart(Type Ty, Optional<OptionalTypeKind> optionalKind) {
|
||||
@@ -89,8 +128,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ostream &cPrologueOS;
|
||||
PrimitiveTypeMapping &typeMapping;
|
||||
SwiftToClangInteropContext &interopContext;
|
||||
OutputLanguageMode languageMode;
|
||||
FunctionSignatureTypeUse typeUseKind;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
@@ -105,7 +147,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
|
||||
StringRef name, bool isInOutParam) {
|
||||
// FIXME: add support for noescape and PrintMultiPartType,
|
||||
// see DeclAndTypePrinter::print.
|
||||
CFunctionSignatureTypePrinter typePrinter(os, typeMapping, outputLang);
|
||||
CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping,
|
||||
outputLang, interopContext);
|
||||
typePrinter.visit(ty, optionalKind);
|
||||
|
||||
if (isInOutParam) {
|
||||
@@ -119,18 +162,37 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
|
||||
};
|
||||
|
||||
// Print out the return type.
|
||||
OptionalTypeKind retKind;
|
||||
Type objTy;
|
||||
std::tie(objTy, retKind) =
|
||||
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
|
||||
CFunctionSignatureTypePrinter typePrinter(os, typeMapping, outputLang);
|
||||
typePrinter.visit(objTy, retKind);
|
||||
bool isIndirectReturnType =
|
||||
kind == FunctionSignatureKind::CFunctionProto &&
|
||||
interopContext.getIrABIDetails().shouldReturnIndirectly(resultTy);
|
||||
if (!isIndirectReturnType) {
|
||||
OptionalTypeKind retKind;
|
||||
Type objTy;
|
||||
std::tie(objTy, retKind) =
|
||||
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
|
||||
CFunctionSignatureTypePrinter typePrinter(
|
||||
os, cPrologueOS, typeMapping, outputLang, interopContext,
|
||||
FunctionSignatureTypeUse::ReturnType);
|
||||
typePrinter.visit(objTy, retKind);
|
||||
} else {
|
||||
os << "void";
|
||||
}
|
||||
|
||||
os << ' ' << name << '(';
|
||||
|
||||
bool HasParams = false;
|
||||
// Indirect result is passed in as the first parameter.
|
||||
if (isIndirectReturnType) {
|
||||
assert(kind == FunctionSignatureKind::CFunctionProto);
|
||||
HasParams = true;
|
||||
// FIXME: it would be nice to print out the C struct type here.
|
||||
os << "SWIFT_INDIRECT_RESULT void * _Nonnull";
|
||||
}
|
||||
// Print out the parameter types.
|
||||
auto params = FD->getParameters();
|
||||
if (params->size()) {
|
||||
if (HasParams)
|
||||
os << ", ";
|
||||
size_t paramIndex = 1;
|
||||
llvm::interleaveComma(*params, os, [&](const ParamDecl *param) {
|
||||
OptionalTypeKind argKind;
|
||||
@@ -149,9 +211,89 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
|
||||
print(objTy, argKind, paramName, param->isInOut());
|
||||
++paramIndex;
|
||||
});
|
||||
} else if (kind == FunctionSignatureKind::CFunctionProto) {
|
||||
} else if (kind == FunctionSignatureKind::CFunctionProto && !HasParams) {
|
||||
// Emit 'void' in an empty parameter list for C function declarations.
|
||||
os << "void";
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
|
||||
void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
|
||||
const ParamDecl *param, StringRef name) {
|
||||
auto namePrinter = [&]() { ClangSyntaxPrinter(os).printIdentifier(name); };
|
||||
auto type = param->getType();
|
||||
if (!isKnownCxxType(type, typeMapping)) {
|
||||
if (auto *structDecl = type->getStructOrBoundGenericStruct()) {
|
||||
ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext)
|
||||
.printParameterCxxToCUseScaffold(
|
||||
interopContext.getIrABIDetails().shouldPassIndirectly(type),
|
||||
structDecl, namePrinter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Primitive types are passed directly without any conversions.
|
||||
namePrinter();
|
||||
}
|
||||
|
||||
void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
|
||||
StringRef swiftSymbolName, Type resultTy, ParameterList *params) {
|
||||
auto printCallToCFunc = [&](Optional<StringRef> additionalParam) {
|
||||
os << cxx_synthesis::getCxxImplNamespaceName() << "::" << swiftSymbolName
|
||||
<< '(';
|
||||
|
||||
bool hasParams = false;
|
||||
if (additionalParam) {
|
||||
hasParams = true;
|
||||
os << *additionalParam;
|
||||
}
|
||||
|
||||
if (params->size()) {
|
||||
if (hasParams)
|
||||
os << ", ";
|
||||
size_t index = 1;
|
||||
interleaveComma(*params, os, [&](const ParamDecl *param) {
|
||||
if (param->isInOut()) {
|
||||
os << "&";
|
||||
}
|
||||
|
||||
if (param->hasName()) {
|
||||
printCxxToCFunctionParameterUse(param, param->getName().str());
|
||||
} else {
|
||||
std::string paramName;
|
||||
llvm::raw_string_ostream paramOS(paramName);
|
||||
paramOS << "_" << index;
|
||||
printCxxToCFunctionParameterUse(param, paramOS.str());
|
||||
}
|
||||
++index;
|
||||
});
|
||||
}
|
||||
|
||||
os << ')';
|
||||
};
|
||||
|
||||
// Values types are returned either direcly in their C representation, or
|
||||
// indirectly by a pointer.
|
||||
if (!isKnownCxxType(resultTy, typeMapping)) {
|
||||
if (auto *structDecl = resultTy->getStructOrBoundGenericStruct()) {
|
||||
bool isIndirect =
|
||||
interopContext.getIrABIDetails().shouldReturnIndirectly(resultTy);
|
||||
ClangValueTypePrinter valueTypePrinter(os, cPrologueOS, typeMapping,
|
||||
interopContext);
|
||||
if (isIndirect) {
|
||||
valueTypePrinter.printValueTypeIndirectReturnScaffold(
|
||||
structDecl, [&](StringRef returnParam) {
|
||||
printCallToCFunc(/*additionalParam=*/returnParam);
|
||||
});
|
||||
} else {
|
||||
valueTypePrinter.printValueTypeDirectReturnScaffold(
|
||||
structDecl, [&]() { printCallToCFunc(/*additionalParam=*/None); });
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Primitive values are returned directly without any conversions.
|
||||
os << " return ";
|
||||
printCallToCFunc(/*additionalParam=*/None);
|
||||
os << ";\n";
|
||||
}
|
||||
|
||||
@@ -21,15 +21,20 @@
|
||||
namespace swift {
|
||||
|
||||
class FuncDecl;
|
||||
class ParamDecl;
|
||||
class ParameterList;
|
||||
class PrimitiveTypeMapping;
|
||||
class SwiftToClangInteropContext;
|
||||
|
||||
/// Responsible for printing a Swift function decl or type in C or C++ mode, to
|
||||
/// be included in a Swift module's generated clang header.
|
||||
class DeclAndTypeClangFunctionPrinter {
|
||||
public:
|
||||
DeclAndTypeClangFunctionPrinter(raw_ostream &os,
|
||||
PrimitiveTypeMapping &typeMapping)
|
||||
: os(os), typeMapping(typeMapping) {}
|
||||
DeclAndTypeClangFunctionPrinter(raw_ostream &os, raw_ostream &cPrologueOS,
|
||||
PrimitiveTypeMapping &typeMapping,
|
||||
SwiftToClangInteropContext &interopContext)
|
||||
: os(os), cPrologueOS(cPrologueOS), typeMapping(typeMapping),
|
||||
interopContext(interopContext) {}
|
||||
|
||||
/// What kind of function signature should be emitted for the given Swift
|
||||
/// function.
|
||||
@@ -45,9 +50,20 @@ public:
|
||||
void printFunctionSignature(FuncDecl *FD, StringRef name, Type resultTy,
|
||||
FunctionSignatureKind kind);
|
||||
|
||||
/// Print the use of the C++ function thunk parameter as it's passed to the C
|
||||
/// function declaration.
|
||||
void printCxxToCFunctionParameterUse(const ParamDecl *param, StringRef name);
|
||||
|
||||
/// Print the body of the inline C++ function thunk that calls the underlying
|
||||
/// Swift function.
|
||||
void printCxxThunkBody(StringRef swiftSymbolName, Type resultTy,
|
||||
ParameterList *params);
|
||||
|
||||
private:
|
||||
raw_ostream &os;
|
||||
raw_ostream &cPrologueOS;
|
||||
PrimitiveTypeMapping &typeMapping;
|
||||
SwiftToClangInteropContext &interopContext;
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "PrintClangValueType.h"
|
||||
#include "ClangSyntaxPrinter.h"
|
||||
#include "OutputLanguageMode.h"
|
||||
#include "PrimitiveTypeMapping.h"
|
||||
#include "SwiftToClangInteropContext.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ParameterList.h"
|
||||
@@ -24,6 +25,32 @@
|
||||
|
||||
using namespace swift;
|
||||
|
||||
/// Print out the C type name of a struct/enum declaration.
|
||||
static void printCTypeName(raw_ostream &os, const NominalTypeDecl *type) {
|
||||
ClangSyntaxPrinter printer(os);
|
||||
printer.printModuleNameCPrefix(*type->getParentModule());
|
||||
// FIXME: add nested type qualifiers to fully disambiguate the name.
|
||||
printer.printIdentifier(type->getName().str());
|
||||
}
|
||||
|
||||
/// Print out the C++ type name of a struct/enum declaration.
|
||||
static void printCxxTypeName(raw_ostream &os, const NominalTypeDecl *type) {
|
||||
// FIXME: Print namespace qualifiers for references from other modules.
|
||||
// FIXME: Print class qualifiers for nested class references.
|
||||
ClangSyntaxPrinter(os).printIdentifier(type->getName().str());
|
||||
}
|
||||
|
||||
static void
|
||||
printCValueTypeStorageStruct(raw_ostream &os, const NominalTypeDecl *typeDecl,
|
||||
IRABIDetailsProvider::SizeAndAlignment layout) {
|
||||
os << "struct ";
|
||||
printCTypeName(os, typeDecl);
|
||||
os << " {\n";
|
||||
os << " _Alignas(" << layout.alignment << ") ";
|
||||
os << "char _storage[" << layout.size << "];\n";
|
||||
os << "};\n\n";
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printStructDecl(const StructDecl *SD) {
|
||||
auto typeSizeAlign =
|
||||
interopContext.getIrABIDetails().getTypeSizeAlignment(SD);
|
||||
@@ -36,12 +63,230 @@ void ClangValueTypePrinter::printStructDecl(const StructDecl *SD) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClangSyntaxPrinter printer(os);
|
||||
|
||||
// Print out a forward declaration of the "hidden" _impl class.
|
||||
printer.printNamespace(cxx_synthesis::getCxxImplNamespaceName(),
|
||||
[&](raw_ostream &os) {
|
||||
os << "class _impl_";
|
||||
printer.printIdentifier(SD->getName().str());
|
||||
os << ";\n";
|
||||
});
|
||||
|
||||
// Print out the C++ class itself.
|
||||
os << "class ";
|
||||
ClangSyntaxPrinter(os).printIdentifier(SD->getName().str());
|
||||
os << " final {\n";
|
||||
// FIXME: Print the other members of the struct.
|
||||
os << "private:\n";
|
||||
|
||||
// Print out private default constructor.
|
||||
os << " inline ";
|
||||
printer.printIdentifier(SD->getName().str());
|
||||
os << "() {}\n";
|
||||
// Print out '_make' function which returns an unitialized instance for
|
||||
// passing to Swift.
|
||||
os << " static inline ";
|
||||
printer.printIdentifier(SD->getName().str());
|
||||
os << " _make() { return ";
|
||||
printer.printIdentifier(SD->getName().str());
|
||||
os << "(); }\n";
|
||||
// Print out the private accessors to the underlying Swift value storage.
|
||||
os << " inline const char * _Nonnull _getOpaquePointer() const { return "
|
||||
"_storage; }\n";
|
||||
os << " inline char * _Nonnull _getOpaquePointer() { return _storage; }\n";
|
||||
os << "\n";
|
||||
|
||||
// Print out the storage for the value type.
|
||||
os << " alignas(" << typeSizeAlign->alignment << ") ";
|
||||
os << "char _storage[" << typeSizeAlign->size << "];\n";
|
||||
os << "};\n";
|
||||
// Wrap up the value type.
|
||||
os << " friend class " << cxx_synthesis::getCxxImplNamespaceName()
|
||||
<< "::_impl_";
|
||||
ClangSyntaxPrinter(os).printIdentifier(SD->getName().str());
|
||||
os << ";\n";
|
||||
os << "};\n\n";
|
||||
|
||||
// Print out the "hidden" _impl class.
|
||||
printer.printNamespace(
|
||||
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
|
||||
os << "class _impl_";
|
||||
printer.printIdentifier(SD->getName().str());
|
||||
os << " {\n";
|
||||
os << "public:\n";
|
||||
|
||||
os << " static inline char * _Nonnull getOpaquePointer(";
|
||||
printCxxTypeName(os, SD);
|
||||
os << " &object) { return object._getOpaquePointer(); }\n";
|
||||
|
||||
os << " static inline const char * _Nonnull getOpaquePointer(const ";
|
||||
printCxxTypeName(os, SD);
|
||||
os << " &object) { return object._getOpaquePointer(); }\n";
|
||||
|
||||
os << " template<class T>\n";
|
||||
os << " static inline ";
|
||||
printCxxTypeName(os, SD);
|
||||
os << " returnNewValue(T callable) {\n";
|
||||
os << " auto result = ";
|
||||
printCxxTypeName(os, SD);
|
||||
os << "::_make();\n";
|
||||
os << " callable(result._getOpaquePointer());\n";
|
||||
os << " return result;\n";
|
||||
os << " }\n";
|
||||
|
||||
os << "};\n";
|
||||
});
|
||||
|
||||
printCValueTypeStorageStruct(cPrologueOS, SD, *typeSizeAlign);
|
||||
}
|
||||
|
||||
/// Print out the C stub struct that's used to pass/return a value type directly
|
||||
/// to/from swiftcc function.
|
||||
static void
|
||||
printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
|
||||
PrimitiveTypeMapping &typeMapping,
|
||||
SwiftToClangInteropContext &interopContext) {
|
||||
|
||||
auto printStubCTypeName = [&]() {
|
||||
os << "swift_interop_stub_";
|
||||
printCTypeName(os, SD);
|
||||
};
|
||||
// Print out a C stub for this value type.
|
||||
os << "// Stub struct to be used to pass/return values to/from Swift "
|
||||
"functions.\n";
|
||||
os << "struct ";
|
||||
printStubCTypeName();
|
||||
os << " {\n";
|
||||
llvm::SmallVector<std::pair<clang::CharUnits, clang::CharUnits>, 8> fields;
|
||||
interopContext.getIrABIDetails().enumerateDirectPassingRecordMembers(
|
||||
SD->getDeclaredType(),
|
||||
[&](clang::CharUnits offset, clang::CharUnits end, Type t) {
|
||||
auto info =
|
||||
typeMapping.getKnownCTypeInfo(t->getNominalOrBoundGenericNominal());
|
||||
if (!info)
|
||||
return;
|
||||
os << " " << info->name;
|
||||
if (info->canBeNullable)
|
||||
os << " _Null_unspecified";
|
||||
os << " _" << (fields.size() + 1) << ";\n";
|
||||
fields.push_back(std::make_pair(offset, end));
|
||||
});
|
||||
|
||||
// cPrologueOS << " _Alignas(" << typeSizeAlign->alignment << ") ";
|
||||
// cPrologueOS << "char _storage[" << typeSizeAlign->size << "];\n";
|
||||
os << "};\n\n";
|
||||
|
||||
// Emit a stub that returns a value directly from swiftcc function.
|
||||
os << "static inline void swift_interop_returnDirect_";
|
||||
printCTypeName(os, SD);
|
||||
os << "(char * _Nonnull result, struct ";
|
||||
printStubCTypeName();
|
||||
os << " value";
|
||||
os << ") __attribute__((always_inline)) {\n";
|
||||
for (size_t i = 0; i < fields.size(); ++i) {
|
||||
os << " memcpy(result + " << fields[i].first.getQuantity() << ", "
|
||||
<< "&value._" << (i + 1) << ", "
|
||||
<< (fields[i].second - fields[i].first).getQuantity() << ");\n";
|
||||
}
|
||||
os << "}\n\n";
|
||||
|
||||
// Emit a stub that is used to pass value type directly to swiftcc function.
|
||||
os << "static inline struct ";
|
||||
printStubCTypeName();
|
||||
os << " swift_interop_passDirect_";
|
||||
printCTypeName(os, SD);
|
||||
os << "(const char * _Nonnull value) __attribute__((always_inline)) {\n";
|
||||
os << " struct ";
|
||||
printStubCTypeName();
|
||||
os << " result;\n";
|
||||
for (size_t i = 0; i < fields.size(); ++i) {
|
||||
os << " memcpy(&result._" << (i + 1) << ", value + "
|
||||
<< fields[i].first.getQuantity() << ", "
|
||||
<< (fields[i].second - fields[i].first).getQuantity() << ");\n";
|
||||
}
|
||||
os << " return result;\n";
|
||||
os << "}\n\n";
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printCStubTypeName(const NominalTypeDecl *type) {
|
||||
os << "swift_interop_stub_";
|
||||
printCTypeName(os, type);
|
||||
// Ensure the stub is declared in the header.
|
||||
interopContext.runIfStubForDeclNotEmitted(type, [&]() {
|
||||
printCStructStubForDirectPassing(cPrologueOS, type, typeMapping,
|
||||
interopContext);
|
||||
});
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printValueTypeParameterType(
|
||||
const NominalTypeDecl *type, OutputLanguageMode outputLang) {
|
||||
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
|
||||
if (outputLang != OutputLanguageMode::Cxx) {
|
||||
// C functions only take stub values directly as parameters.
|
||||
os << "struct ";
|
||||
printCStubTypeName(type);
|
||||
return;
|
||||
}
|
||||
os << "const ";
|
||||
printCxxTypeName(os, type);
|
||||
os << '&';
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printParameterCxxToCUseScaffold(
|
||||
bool isIndirect, const NominalTypeDecl *type,
|
||||
llvm::function_ref<void()> cxxParamPrinter) {
|
||||
// A Swift value type is passed to its underlying Swift function
|
||||
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
|
||||
if (!isIndirect) {
|
||||
os << cxx_synthesis::getCxxImplNamespaceName() << "::"
|
||||
<< "swift_interop_passDirect_";
|
||||
printCTypeName(os, type);
|
||||
os << '(';
|
||||
}
|
||||
os << cxx_synthesis::getCxxImplNamespaceName() << "::_impl_";
|
||||
ClangSyntaxPrinter(os).printIdentifier(type->getName().str());
|
||||
os << "::getOpaquePointer(";
|
||||
cxxParamPrinter();
|
||||
os << ')';
|
||||
if (!isIndirect)
|
||||
os << ')';
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printValueTypeReturnType(
|
||||
const NominalTypeDecl *type, OutputLanguageMode outputLang) {
|
||||
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
|
||||
if (outputLang == OutputLanguageMode::Cxx) {
|
||||
printCxxTypeName(os, type);
|
||||
} else {
|
||||
os << "struct ";
|
||||
printCStubTypeName(type);
|
||||
}
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold(
|
||||
const NominalTypeDecl *type,
|
||||
llvm::function_ref<void(StringRef)> bodyPrinter) {
|
||||
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
|
||||
os << " return " << cxx_synthesis::getCxxImplNamespaceName() << "::_impl_";
|
||||
ClangSyntaxPrinter(os).printIdentifier(type->getName().str());
|
||||
os << "::returnNewValue([&](void * _Nonnull result) {\n ";
|
||||
bodyPrinter("result");
|
||||
os << ";\n";
|
||||
os << " });\n";
|
||||
}
|
||||
|
||||
void ClangValueTypePrinter::printValueTypeDirectReturnScaffold(
|
||||
const NominalTypeDecl *type, llvm::function_ref<void()> bodyPrinter) {
|
||||
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
|
||||
os << " return " << cxx_synthesis::getCxxImplNamespaceName() << "::_impl_";
|
||||
ClangSyntaxPrinter(os).printIdentifier(type->getName().str());
|
||||
os << "::returnNewValue([&](char * _Nonnull result) {\n";
|
||||
os << " ";
|
||||
os << cxx_synthesis::getCxxImplNamespaceName() << "::"
|
||||
<< "swift_interop_returnDirect_";
|
||||
printCTypeName(os, type);
|
||||
os << "(result, ";
|
||||
bodyPrinter();
|
||||
os << ");\n";
|
||||
os << " });\n";
|
||||
}
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
#ifndef SWIFT_PRINTASCLANG_PRINTCLANGVALUETYPE_H
|
||||
#define SWIFT_PRINTASCLANG_PRINTCLANGVALUETYPE_H
|
||||
|
||||
#include "OutputLanguageMode.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
class NominalTypeDecl;
|
||||
class PrimitiveTypeMapping;
|
||||
class StructDecl;
|
||||
class SwiftToClangInteropContext;
|
||||
|
||||
@@ -25,16 +29,55 @@ class SwiftToClangInteropContext;
|
||||
/// be included in a Swift module's generated clang header.
|
||||
class ClangValueTypePrinter {
|
||||
public:
|
||||
ClangValueTypePrinter(raw_ostream &os,
|
||||
ClangValueTypePrinter(raw_ostream &os, raw_ostream &cPrologueOS,
|
||||
PrimitiveTypeMapping &typeMapping,
|
||||
SwiftToClangInteropContext &interopContext)
|
||||
: os(os), interopContext(interopContext) {}
|
||||
: os(os), cPrologueOS(cPrologueOS), typeMapping(typeMapping),
|
||||
interopContext(interopContext) {}
|
||||
|
||||
/// Print the C struct thunk or the C++ class definition that
|
||||
/// corresponds to the given structure declaration.
|
||||
void printStructDecl(const StructDecl *SD);
|
||||
|
||||
/// Print the pararameter type that referes to a Swift struct type in C/C++.
|
||||
void printValueTypeParameterType(const NominalTypeDecl *type,
|
||||
OutputLanguageMode outputLang);
|
||||
|
||||
/// Print the use of a C++ struct/enum parameter value as it's passed to the
|
||||
/// underlying C function that represents the native Swift function.
|
||||
void
|
||||
printParameterCxxToCUseScaffold(bool isIndirect, const NominalTypeDecl *type,
|
||||
llvm::function_ref<void()> cxxParamPrinter);
|
||||
|
||||
/// Print the return type that refers to a Swift struct type in C/C++.
|
||||
void printValueTypeReturnType(const NominalTypeDecl *typeDecl,
|
||||
OutputLanguageMode outputLang);
|
||||
|
||||
/// Print the supporting code that's required to indirectly return a C++
|
||||
/// class that represents a Swift value type as it's being indirectly passed
|
||||
/// from the C function that represents the native Swift function.
|
||||
void printValueTypeIndirectReturnScaffold(
|
||||
const NominalTypeDecl *typeDecl,
|
||||
llvm::function_ref<void(StringRef)> bodyPrinter);
|
||||
|
||||
/// Print the supporting code that's required to directly return a C++ class
|
||||
/// that represents a Swift value type as it's being returned from the C
|
||||
/// function that represents the native Swift function.
|
||||
void
|
||||
printValueTypeDirectReturnScaffold(const NominalTypeDecl *typeDecl,
|
||||
llvm::function_ref<void()> bodyPrinter);
|
||||
|
||||
private:
|
||||
/// Prints out the C stub name used to pass/return value directly for the
|
||||
/// given value type.
|
||||
///
|
||||
/// If the C stub isn't declared yet in the emitted header, that declaration
|
||||
/// will be emitted by this function.
|
||||
void printCStubTypeName(const NominalTypeDecl *type);
|
||||
|
||||
raw_ostream &os;
|
||||
raw_ostream &cPrologueOS;
|
||||
PrimitiveTypeMapping &typeMapping;
|
||||
SwiftToClangInteropContext &interopContext;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,3 +26,10 @@ IRABIDetailsProvider &SwiftToClangInteropContext::getIrABIDetails() {
|
||||
irABIDetails = std::make_unique<IRABIDetailsProvider>(mod, irGenOpts);
|
||||
return *irABIDetails;
|
||||
}
|
||||
|
||||
void SwiftToClangInteropContext::runIfStubForDeclNotEmitted(
|
||||
const Decl *d, llvm::function_ref<void(void)> function) {
|
||||
auto result = emittedStubs.insert(d);
|
||||
if (result.second)
|
||||
function();
|
||||
}
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
#ifndef SWIFT_PRINTASCLANG_SWIFTTOCLANGINTEROPCONTEXT_H
|
||||
#define SWIFT_PRINTASCLANG_SWIFTTOCLANGINTEROPCONTEXT_H
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <memory>
|
||||
|
||||
namespace swift {
|
||||
|
||||
class Decl;
|
||||
class IRABIDetailsProvider;
|
||||
class IRGenOptions;
|
||||
class ModuleDecl;
|
||||
@@ -32,10 +35,16 @@ public:
|
||||
|
||||
IRABIDetailsProvider &getIrABIDetails();
|
||||
|
||||
// Runs the given function if we haven't emitted some context-specific stub
|
||||
// for the given declaration yet.
|
||||
void runIfStubForDeclNotEmitted(const Decl *d,
|
||||
llvm::function_ref<void(void)> function);
|
||||
|
||||
private:
|
||||
ModuleDecl &mod;
|
||||
const IRGenOptions &irGenOpts;
|
||||
std::unique_ptr<IRABIDetailsProvider> irABIDetails;
|
||||
llvm::DenseSet<const Decl *> emittedStubs;
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
29
test/Inputs/clang-importer-sdk/usr/include/string.h
Normal file
29
test/Inputs/clang-importer-sdk/usr/include/string.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef SDK_STRING_H
|
||||
#define SDK_STRING_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void* memcpy(void* s1, const void* s2, size_t n);
|
||||
void* memmove(void* s1, const void* s2, size_t n);
|
||||
char* strcpy (char* s1, const char* s2);
|
||||
char* strncpy(char* s1, const char* s2, size_t n);
|
||||
char* strcat (char* s1, const char* s2);
|
||||
char* strncat(char* s1, const char* s2, size_t n);
|
||||
int memcmp(const void* s1, const void* s2, size_t n);
|
||||
int strcmp (const char* s1, const char* s2);
|
||||
int strncmp(const char* s1, const char* s2, size_t n);
|
||||
int strcoll(const char* s1, const char* s2);
|
||||
size_t strxfrm(char* s1, const char* s2, size_t n);
|
||||
const void* memchr(const void* s, int c, size_t n);
|
||||
const char* strchr(const char* s, int c);
|
||||
size_t strcspn(const char* s1, const char* s2);
|
||||
const char* strpbrk(const char* s1, const char* s2);
|
||||
const char* strrchr(const char* s, int c);
|
||||
size_t strspn(const char* s1, const char* s2);
|
||||
const char* strstr(const char* s1, const char* s2);
|
||||
char* strtok(char* s1, const char* s2);
|
||||
void* memset(void* s, int c, size_t n);
|
||||
char* strerror(int errnum);
|
||||
size_t strlen(const char* s);
|
||||
|
||||
#endif // SDK_STRING_H
|
||||
@@ -0,0 +1,30 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-frontend %S/large-structs-pass-return-indirect-in-c.swift -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
|
||||
// RUN: %target-interop-build-clang -c %s -I %t -o %t/swift-structs-execution.o
|
||||
// RUN: %target-interop-build-swift %S/large-structs-pass-return-indirect-in-c.swift -o %t/swift-structs-execution -Xlinker %t/swift-structs-execution.o -module-name Structs -Xfrontend -entry-point-function-name -Xfrontend swiftMain
|
||||
|
||||
// RUN: %target-codesign %t/swift-structs-execution
|
||||
// RUN: %target-run %t/swift-structs-execution | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
#include <assert.h>
|
||||
#include "structs.h"
|
||||
|
||||
int main() {
|
||||
// printStructSeveralI64(returnNewStructSeveralI64(42))
|
||||
struct Structs_StructSeveralI64 structSeveralI64;
|
||||
$s7Structs25returnNewStructSeveralI641iAA0deF0Vs5Int64V_tF(&structSeveralI64, 42);
|
||||
$s7Structs21printStructSeveralI64yyAA0cdE0VF(&structSeveralI64);
|
||||
// CHECK: StructSeveralI64.1 = 42, .2 = 0, .3 = -17, .4 = 12345612, .5 = -65535
|
||||
|
||||
// printStructSeveralI64(passThroughStructSeveralI64(581, returnNewStructSeveralI64(42), 5.0))
|
||||
struct Structs_StructSeveralI64 structSeveralI64_copy;
|
||||
$s7Structs27passThroughStructSeveralI641i_1jAA0deF0Vs5Int64V_AFSftF(&structSeveralI64_copy,
|
||||
581, &structSeveralI64, 5.0f);
|
||||
$s7Structs21printStructSeveralI64yyAA0cdE0VF(&structSeveralI64_copy);
|
||||
// CHECK-NEXT: StructSeveralI64.1 = 42, .2 = 581, .3 = -17, .4 = -12345612, .5 = -65530
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
// RUN: %FileCheck %s < %t/structs.h
|
||||
|
||||
// RUN: %check-interop-c-header-in-clang(%t/structs.h)
|
||||
|
||||
public struct StructSeveralI64 {
|
||||
let x1, x2, x3, x4, x5: Int64
|
||||
}
|
||||
// CHECK: struct Structs_StructSeveralI64 {
|
||||
// CHECK-NEXT: _Alignas(8) char _storage[40];
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK_NOT: swift_interop
|
||||
|
||||
public func returnNewStructSeveralI64(i: Int64) -> StructSeveralI64 {
|
||||
return StructSeveralI64(x1: i, x2: 0, x3: -17, x4: 12345612, x5: -0xFFFF)
|
||||
}
|
||||
|
||||
public func passThroughStructSeveralI64(i: Int64, _ x: StructSeveralI64, j: Float) -> StructSeveralI64 {
|
||||
return StructSeveralI64(x1: x.x1, x2: x.x2 + i, x3: x.x3, x4: -x.x4, x5: x.x5 + Int64(j))
|
||||
}
|
||||
|
||||
public func printStructSeveralI64(_ x: StructSeveralI64) {
|
||||
print("StructSeveralI64.1 = \(x.x1), .2 = \(x.x2), .3 = \(x.x3), .4 = \(x.x4), .5 = \(x.x5)")
|
||||
}
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs27passThroughStructSeveralI641i_1jAA0deF0Vs5Int64V_AFSftF(SWIFT_INDIRECT_RESULT void * _Nonnull, int64_t i, const void * _Nonnull x, float j) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs21printStructSeveralI64yyAA0cdE0VF(const void * _Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs25returnNewStructSeveralI641iAA0deF0Vs5Int64V_tF(SWIFT_INDIRECT_RESULT void * _Nonnull, int64_t i) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
@@ -0,0 +1,90 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-frontend %S/small-structs-pass-return-direct-in-c.swift -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
|
||||
// RUN: %target-interop-build-clang -c %s -I %t -o %t/swift-structs-execution.o -Wno-incompatible-pointer-types
|
||||
// RUN: %target-interop-build-swift %S/small-structs-pass-return-direct-in-c.swift -o %t/swift-structs-execution -Xlinker %t/swift-structs-execution.o -module-name Structs -Xfrontend -entry-point-function-name -Xfrontend swiftMain
|
||||
|
||||
// RUN: %target-codesign %t/swift-structs-execution
|
||||
// RUN: %target-run %t/swift-structs-execution | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
#include <assert.h>
|
||||
#include "structs.h"
|
||||
|
||||
int main() {
|
||||
// printStructOneI64(returnNewStructOneI64())
|
||||
struct Structs_StructOneI64 structOneI64;
|
||||
swift_interop_returnDirect_Structs_StructOneI64(&structOneI64, $s7Structs21returnNewStructOneI64AA0deF0VyF());
|
||||
$s7Structs17printStructOneI64yyAA0cdE0VF(swift_interop_passDirect_Structs_StructOneI64(&structOneI64));
|
||||
// CHECK: StructOneI64.x = 42
|
||||
|
||||
// printStructOneI64(passThroughStructOneI64(...))
|
||||
struct Structs_StructOneI64 structOneI64_copy;
|
||||
swift_interop_returnDirect_Structs_StructOneI64(&structOneI64_copy,
|
||||
$s7Structs23passThroughStructOneI64yAA0deF0VADF(
|
||||
swift_interop_passDirect_Structs_StructOneI64(&structOneI64)));
|
||||
$s7Structs17printStructOneI64yyAA0cdE0VF(swift_interop_passDirect_Structs_StructOneI64(&structOneI64_copy));
|
||||
// CHECK-NEXT: StructOneI64.x = 42
|
||||
$s7Structs17printStructOneI64yyAA0cdE0VF(swift_interop_passDirect_Structs_StructOneI64(&structOneI64));
|
||||
// CHECK-NEXT: StructOneI64.x = 42
|
||||
|
||||
// printStructTwoI32(returnNewStructTwoI32(11))
|
||||
struct Structs_StructTwoI32 structTwoI32;
|
||||
swift_interop_returnDirect_Structs_StructTwoI32(&structTwoI32,
|
||||
$s7Structs21returnNewStructTwoI32yAA0deF0Vs5Int32VF(11));
|
||||
$s7Structs17printStructTwoI32yyAA0cdE0VF(swift_interop_passDirect_Structs_StructTwoI32(&structTwoI32));
|
||||
// CHECK-NEXT: StructTwoI32.x = 11, y = 22
|
||||
|
||||
// printStructTwoI32(passThroughStructTwoI32(4, ..., 6))
|
||||
struct Structs_StructTwoI32 structTwoI32_copy;
|
||||
swift_interop_returnDirect_Structs_StructTwoI32(&structTwoI32_copy,
|
||||
$s7Structs23passThroughStructTwoI32yAA0deF0Vs5Int32V_AdFtF(4, swift_interop_passDirect_Structs_StructTwoI32(&structTwoI32), 6));
|
||||
$s7Structs17printStructTwoI32yyAA0cdE0VF(swift_interop_passDirect_Structs_StructTwoI32(&structTwoI32_copy));
|
||||
// CHECK-NEXT: StructTwoI32.x = 15, y = 28
|
||||
|
||||
// printStructStructTwoI32_and_OneI16AndOneStruct(... , returnNewStructOneI16AndOneStruct());
|
||||
struct Structs_StructOneI16AndOneStruct structOneI16AndOneStruct;
|
||||
swift_interop_returnDirect_Structs_StructOneI16AndOneStruct(&structOneI16AndOneStruct,
|
||||
$s7Structs024returnNewStructOneI16AndeD0AA0defgeD0VyF());
|
||||
$s7Structs011printStructc20TwoI32_and_OneI16AndgC0yyAA0cdE0V_AA0cghigC0VtF(
|
||||
swift_interop_passDirect_Structs_StructTwoI32(&structTwoI32),
|
||||
swift_interop_passDirect_Structs_StructOneI16AndOneStruct(&structOneI16AndOneStruct));
|
||||
// CHECK-NEXT: StructTwoI32.x = 11, y = 22
|
||||
// CHECK-NEXT: StructOneI16AndOneStruct.x = 255, y.x = 5, y.y = 72
|
||||
|
||||
// let x = returnNewStructU16AndPointer(...)
|
||||
// getStructU16AndPointer_x(x)
|
||||
// getStructU16AndPointer_y(y)
|
||||
char c = 'A';
|
||||
struct Structs_StructU16AndPointer structU16AndPointer;
|
||||
swift_interop_returnDirect_Structs_StructU16AndPointer(&structU16AndPointer,
|
||||
$s7Structs28returnNewStructU16AndPointeryAA0defG0VSvF(&c));
|
||||
assert($s7Structs24getStructU16AndPointer_xys5UInt8VAA0cdeF0VF(
|
||||
swift_interop_passDirect_Structs_StructU16AndPointer(&structU16AndPointer)) == 55);
|
||||
assert($s7Structs24getStructU16AndPointer_yySvAA0cdeF0VF(
|
||||
swift_interop_passDirect_Structs_StructU16AndPointer(&structU16AndPointer)) == &c);
|
||||
|
||||
// let x = returnNewStructDoubleAndFloat()
|
||||
// getStructDoubleAndFloat_x(x)
|
||||
// getStructDoubleAndFloat_y(x)
|
||||
double doubleValue = 1.25;
|
||||
float floatValue = -5.0f;
|
||||
struct Structs_StructDoubleAndFloat structDoubleAndFloat;
|
||||
swift_interop_returnDirect_Structs_StructDoubleAndFloat(&structDoubleAndFloat,
|
||||
$s7Structs29returnNewStructDoubleAndFloatyAA0defG0VSf_SdtF(floatValue, doubleValue));
|
||||
assert($s7Structs25getStructDoubleAndFloat_xySdAA0cdeF0VF(
|
||||
swift_interop_passDirect_Structs_StructDoubleAndFloat(&structDoubleAndFloat)) == doubleValue);
|
||||
assert($s7Structs25getStructDoubleAndFloat_yySfAA0cdeF0VF(
|
||||
swift_interop_passDirect_Structs_StructDoubleAndFloat(&structDoubleAndFloat)) == floatValue);
|
||||
|
||||
// printStructI8AndU32AndI16(returnNewStructI8AndU32AndI16())
|
||||
struct Structs_StructI8AndU32AndI16 structI8AndU32AndI16;
|
||||
swift_interop_returnDirect_Structs_StructI8AndU32AndI16(&structI8AndU32AndI16,
|
||||
$s7Structs023returnNewStructI8AndU32F3I16AA0defgfH0VyF());
|
||||
$s7Structs019printStructI8AndU32E3I16yyAA0cdefeG0VF(
|
||||
swift_interop_passDirect_Structs_StructI8AndU32AndI16(&structI8AndU32AndI16));
|
||||
// CHECK-NEXT: StructI8AndU32AndI16.x = -100, y = 123456, z = -3456
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
// RUN: %FileCheck %s < %t/structs.h
|
||||
|
||||
// RUN: %check-interop-c-header-in-clang(%t/structs.h -Wno-unused-function)
|
||||
|
||||
public struct StructOneI64 {
|
||||
let x: Int64
|
||||
}
|
||||
|
||||
public struct StructTwoI32 {
|
||||
let x, y: Int32
|
||||
}
|
||||
|
||||
public struct StructOneI16AndOneStruct {
|
||||
let x: Int16
|
||||
let y: StructTwoI32
|
||||
}
|
||||
|
||||
public struct StructU16AndPointer {
|
||||
let x: UInt8
|
||||
let y: UnsafeMutableRawPointer
|
||||
}
|
||||
|
||||
public struct StructDoubleAndFloat {
|
||||
let x: Double
|
||||
let y: Float
|
||||
}
|
||||
|
||||
public struct StructI8AndU32AndI16 {
|
||||
let x: Int8
|
||||
let y: UInt32
|
||||
let z: Int16
|
||||
}
|
||||
|
||||
// CHECK: struct Structs_StructDoubleAndFloat {
|
||||
// CHECK_NEXT: _Alignas(8) char _storage[12];
|
||||
// CHECK_NEXT: };
|
||||
|
||||
// CHECK: struct Structs_StructI8AndU32AndI16 {
|
||||
// CHECK_NEXT: _Alignas(4) char _storage[10];
|
||||
// CHECK_NEXT: };
|
||||
|
||||
// CHECK: struct Structs_StructOneI16AndOneStruct {
|
||||
// CHECK_NEXT: _Alignas(4) char _storage[12];
|
||||
// CHECK_NEXT: };
|
||||
|
||||
// CHECK: struct Structs_StructOneI64 {
|
||||
// CHECK_NEXT: _Alignas(8) char _storage[8];
|
||||
// CHECK_NEXT: };
|
||||
|
||||
// CHECK: struct Structs_StructTwoI32 {
|
||||
// CHECK_NEXT: _Alignas(4) char _storage[8];
|
||||
// CHECK_NEXT: };
|
||||
|
||||
// CHECK: struct Structs_StructU16AndPointer {
|
||||
// CHECK_NEXT: _Alignas(8) char _storage[16];
|
||||
// CHECK_NEXT: };
|
||||
|
||||
public func returnNewStructOneI64() -> StructOneI64 { return StructOneI64(x: 42 ) }
|
||||
|
||||
public func passThroughStructOneI64(_ x: StructOneI64) -> StructOneI64 { return x }
|
||||
|
||||
public func printStructOneI64(_ x: StructOneI64) {
|
||||
print("StructOneI64.x = \(x.x)")
|
||||
}
|
||||
|
||||
public func returnNewStructTwoI32(_ x: Int32) -> StructTwoI32 { return StructTwoI32(x: x, y: x * 2) }
|
||||
|
||||
public func passThroughStructTwoI32(_ i: Int32, _ x: StructTwoI32, _ j: Int32) -> StructTwoI32 {
|
||||
return StructTwoI32(x: x.x + i, y: x.y + j)
|
||||
}
|
||||
|
||||
public func printStructTwoI32(_ x: StructTwoI32) {
|
||||
print("StructTwoI32.x = \(x.x), y = \(x.y)")
|
||||
}
|
||||
|
||||
public func returnNewStructOneI16AndOneStruct() -> StructOneI16AndOneStruct {
|
||||
return StructOneI16AndOneStruct(x: 0xFF, y: StructTwoI32(x: 5, y: 72))
|
||||
}
|
||||
|
||||
public func printStructStructTwoI32_and_OneI16AndOneStruct(_ y: StructTwoI32, _ x: StructOneI16AndOneStruct) {
|
||||
printStructTwoI32(y)
|
||||
print("StructOneI16AndOneStruct.x = \(x.x), y.x = \(x.y.x), y.y = \(x.y.y)")
|
||||
}
|
||||
|
||||
public func returnNewStructU16AndPointer(_ x: UnsafeMutableRawPointer) -> StructU16AndPointer {
|
||||
return StructU16AndPointer(x: 55, y: x)
|
||||
}
|
||||
|
||||
public func getStructU16AndPointer_x(_ x: StructU16AndPointer) -> UInt8 { return x.x }
|
||||
|
||||
public func getStructU16AndPointer_y(_ x: StructU16AndPointer) -> UnsafeMutableRawPointer { return x.y }
|
||||
|
||||
public func returnNewStructDoubleAndFloat(_ y: Float, _ x: Double) -> StructDoubleAndFloat {
|
||||
return StructDoubleAndFloat(x: x, y: y)
|
||||
}
|
||||
|
||||
public func getStructDoubleAndFloat_x(_ x: StructDoubleAndFloat) -> Double { return x.x }
|
||||
|
||||
public func getStructDoubleAndFloat_y(_ x: StructDoubleAndFloat) -> Float { return x.y }
|
||||
|
||||
public func returnNewStructI8AndU32AndI16() -> StructI8AndU32AndI16 {
|
||||
return StructI8AndU32AndI16(x: -100, y: 123456, z: -3456)
|
||||
}
|
||||
|
||||
public func printStructI8AndU32AndI16(_ x: StructI8AndU32AndI16) {
|
||||
print("StructI8AndU32AndI16.x = \(x.x), y = \(x.y), z = \(x.z)")
|
||||
}
|
||||
|
||||
// CHECK: struct swift_interop_stub_Structs_StructDoubleAndFloat {
|
||||
// CHECK-NEXT: double _1;
|
||||
// CHECK-NEXT: float _2;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: static inline void swift_interop_returnDirect_Structs_StructDoubleAndFloat(char * _Nonnull result, struct swift_interop_stub_Structs_StructDoubleAndFloat value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: memcpy(result + 0, &value._1, 8);
|
||||
// CHECK-NEXT: memcpy(result + 8, &value._2, 4);
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: static inline struct swift_interop_stub_Structs_StructDoubleAndFloat swift_interop_passDirect_Structs_StructDoubleAndFloat(const char * _Nonnull value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: struct swift_interop_stub_Structs_StructDoubleAndFloat result;
|
||||
// CHECK-NEXT: memcpy(&result._1, value + 0, 8);
|
||||
// CHECK-NEXT: memcpy(&result._2, value + 8, 4);
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: SWIFT_EXTERN double $s7Structs25getStructDoubleAndFloat_xySdAA0cdeF0VF(struct swift_interop_stub_Structs_StructDoubleAndFloat x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN float $s7Structs25getStructDoubleAndFloat_yySfAA0cdeF0VF(struct swift_interop_stub_Structs_StructDoubleAndFloat x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: struct swift_interop_stub_Structs_StructU16AndPointer {
|
||||
// CHECK-NEXT: uint8_t _1;
|
||||
// CHECK-NEXT: void * _Null_unspecified _2;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: static inline void swift_interop_returnDirect_Structs_StructU16AndPointer(char * _Nonnull result, struct swift_interop_stub_Structs_StructU16AndPointer value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: memcpy(result + 0, &value._1, 1);
|
||||
// CHECK-NEXT: memcpy(result + 8, &value._2, 8);
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: static inline struct swift_interop_stub_Structs_StructU16AndPointer swift_interop_passDirect_Structs_StructU16AndPointer(const char * _Nonnull value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: struct swift_interop_stub_Structs_StructU16AndPointer result;
|
||||
// CHECK-NEXT: memcpy(&result._1, value + 0, 1);
|
||||
// CHECK-NEXT: memcpy(&result._2, value + 8, 8);
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: SWIFT_EXTERN uint8_t $s7Structs24getStructU16AndPointer_xys5UInt8VAA0cdeF0VF(struct swift_interop_stub_Structs_StructU16AndPointer x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN void * _Nonnull $s7Structs24getStructU16AndPointer_yySvAA0cdeF0VF(struct swift_interop_stub_Structs_StructU16AndPointer x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: struct swift_interop_stub_Structs_StructOneI64 {
|
||||
// CHECK-NEXT: uint64_t _1;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: static inline void swift_interop_returnDirect_Structs_StructOneI64(char * _Nonnull result, struct swift_interop_stub_Structs_StructOneI64 value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: memcpy(result + 0, &value._1, 8);
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: static inline struct swift_interop_stub_Structs_StructOneI64 swift_interop_passDirect_Structs_StructOneI64(const char * _Nonnull value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: struct swift_interop_stub_Structs_StructOneI64 result;
|
||||
// CHECK-NEXT: memcpy(&result._1, value + 0, 8);
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructOneI64 $s7Structs23passThroughStructOneI64yAA0deF0VADF(struct swift_interop_stub_Structs_StructOneI64 x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: struct swift_interop_stub_Structs_StructTwoI32 {
|
||||
// CHECK-NEXT: uint64_t _1;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: static inline void swift_interop_returnDirect_Structs_StructTwoI32(char * _Nonnull result, struct swift_interop_stub_Structs_StructTwoI32 value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: memcpy(result + 0, &value._1, 8);
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: static inline struct swift_interop_stub_Structs_StructTwoI32 swift_interop_passDirect_Structs_StructTwoI32(const char * _Nonnull value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: struct swift_interop_stub_Structs_StructTwoI32 result;
|
||||
// CHECK-NEXT: memcpy(&result._1, value + 0, 8);
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructTwoI32 $s7Structs23passThroughStructTwoI32yAA0deF0Vs5Int32V_AdFtF(int32_t i, struct swift_interop_stub_Structs_StructTwoI32 x, int32_t j) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: struct swift_interop_stub_Structs_StructI8AndU32AndI16 {
|
||||
// CHECK-NEXT: uint64_t _1;
|
||||
// CHECK-NEXT: uint16_t _2;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: static inline void swift_interop_returnDirect_Structs_StructI8AndU32AndI16(char * _Nonnull result, struct swift_interop_stub_Structs_StructI8AndU32AndI16 value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: memcpy(result + 0, &value._1, 8);
|
||||
// CHECK-NEXT: memcpy(result + 8, &value._2, 2);
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: static inline struct swift_interop_stub_Structs_StructI8AndU32AndI16 swift_interop_passDirect_Structs_StructI8AndU32AndI16(const char * _Nonnull value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: struct swift_interop_stub_Structs_StructI8AndU32AndI16 result;
|
||||
// CHECK-NEXT: memcpy(&result._1, value + 0, 8);
|
||||
// CHECK-NEXT: memcpy(&result._2, value + 8, 2);
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs019printStructI8AndU32E3I16yyAA0cdefeG0VF(struct swift_interop_stub_Structs_StructI8AndU32AndI16 x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs17printStructOneI64yyAA0cdE0VF(struct swift_interop_stub_Structs_StructOneI64 x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: struct swift_interop_stub_Structs_StructOneI16AndOneStruct {
|
||||
// CHECK-NEXT: uint64_t _1;
|
||||
// CHECK-NEXT: uint32_t _2;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: static inline void swift_interop_returnDirect_Structs_StructOneI16AndOneStruct(char * _Nonnull result, struct swift_interop_stub_Structs_StructOneI16AndOneStruct value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: memcpy(result + 0, &value._1, 8);
|
||||
// CHECK-NEXT: memcpy(result + 8, &value._2, 4);
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: static inline struct swift_interop_stub_Structs_StructOneI16AndOneStruct swift_interop_passDirect_Structs_StructOneI16AndOneStruct(const char * _Nonnull value) __attribute__((always_inline)) {
|
||||
// CHECK-NEXT: struct swift_interop_stub_Structs_StructOneI16AndOneStruct result;
|
||||
// CHECK-NEXT: memcpy(&result._1, value + 0, 8);
|
||||
// CHECK-NEXT: memcpy(&result._2, value + 8, 4);
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs011printStructc20TwoI32_and_OneI16AndgC0yyAA0cdE0V_AA0cghigC0VtF(struct swift_interop_stub_Structs_StructTwoI32 y, struct swift_interop_stub_Structs_StructOneI16AndOneStruct x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN void $s7Structs17printStructTwoI32yyAA0cdE0VF(struct swift_interop_stub_Structs_StructTwoI32 x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructDoubleAndFloat $s7Structs29returnNewStructDoubleAndFloatyAA0defG0VSf_SdtF(float y, double x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructI8AndU32AndI16 $s7Structs023returnNewStructI8AndU32F3I16AA0defgfH0VyF(void) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructOneI16AndOneStruct $s7Structs024returnNewStructOneI16AndeD0AA0defgeD0VyF(void) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructOneI64 $s7Structs21returnNewStructOneI64AA0deF0VyF(void) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructTwoI32 $s7Structs21returnNewStructTwoI32yAA0deF0Vs5Int32VF(int32_t x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
|
||||
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Structs_StructU16AndPointer $s7Structs28returnNewStructU16AndPointeryAA0defG0VSvF(void * _Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
@@ -0,0 +1,28 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-frontend %S/large-structs-pass-return-indirect-in-cxx.swift -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
|
||||
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-structs-execution.o
|
||||
// RUN: %target-interop-build-swift %S/large-structs-pass-return-indirect-in-cxx.swift -o %t/swift-structs-execution -Xlinker %t/swift-structs-execution.o -module-name Structs -Xfrontend -entry-point-function-name -Xfrontend swiftMain
|
||||
|
||||
// RUN: %target-codesign %t/swift-structs-execution
|
||||
// RUN: %target-run %t/swift-structs-execution | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
#include <assert.h>
|
||||
#include "structs.h"
|
||||
|
||||
int main() {
|
||||
using namespace Structs;
|
||||
|
||||
static_assert(sizeof(StructSeveralI64) == 40);
|
||||
|
||||
printStructSeveralI64(returnNewStructSeveralI64(42));
|
||||
// CHECK: StructSeveralI64.1 = 42, .2 = 0, .3 = -17, .4 = 12345612, .5 = -65535
|
||||
|
||||
StructSeveralI64 structSeveralI64_copy = passThroughStructSeveralI64(100, returnNewStructSeveralI64(11), 6.0);
|
||||
printStructSeveralI64(structSeveralI64_copy);
|
||||
// CHECK-NEXT: StructSeveralI64.1 = 11, .2 = 100, .3 = -17, .4 = -12345612, .5 = -65529
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
// RUN: %FileCheck %s < %t/structs.h
|
||||
|
||||
// RUN: %check-interop-cxx-header-in-clang(%t/structs.h)
|
||||
|
||||
public struct StructSeveralI64 {
|
||||
let x1, x2, x3, x4, x5: Int64
|
||||
}
|
||||
|
||||
// CHECK: class StructSeveralI64 final {
|
||||
|
||||
public func returnNewStructSeveralI64(i: Int64) -> StructSeveralI64 {
|
||||
return StructSeveralI64(x1: i, x2: 0, x3: -17, x4: 12345612, x5: -0xFFFF)
|
||||
}
|
||||
|
||||
public func passThroughStructSeveralI64(i: Int64, _ x: StructSeveralI64, j: Float) -> StructSeveralI64 {
|
||||
return StructSeveralI64(x1: x.x1, x2: x.x2 + i, x3: x.x3, x4: -x.x4, x5: x.x5 + Int64(j))
|
||||
}
|
||||
|
||||
public func printStructSeveralI64(_ x: StructSeveralI64) {
|
||||
print("StructSeveralI64.1 = \(x.x1), .2 = \(x.x2), .3 = \(x.x3), .4 = \(x.x4), .5 = \(x.x5)")
|
||||
}
|
||||
|
||||
// CHECK: inline StructSeveralI64 passThroughStructSeveralI64(int64_t i, const StructSeveralI64& x, float j) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::$s7Structs27passThroughStructSeveralI641i_1jAA0deF0Vs5Int64V_AFSftF(result, i, _impl::_impl_StructSeveralI64::getOpaquePointer(x), j);
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline void printStructSeveralI64(const StructSeveralI64& x) noexcept {
|
||||
// CHECK-NEXT: return _impl::$s7Structs21printStructSeveralI64yyAA0cdE0VF(_impl::_impl_StructSeveralI64::getOpaquePointer(x));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructSeveralI64 returnNewStructSeveralI64(int64_t i) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::$s7Structs25returnNewStructSeveralI641iAA0deF0Vs5Int64V_tF(result, i);
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
@@ -0,0 +1,51 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-frontend %S/small-structs-pass-return-direct-in-cxx.swift -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
|
||||
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-structs-execution.o -Wno-incompatible-pointer-types
|
||||
// RUN: %target-interop-build-swift %S/small-structs-pass-return-direct-in-cxx.swift -o %t/swift-structs-execution -Xlinker %t/swift-structs-execution.o -module-name Structs -Xfrontend -entry-point-function-name -Xfrontend swiftMain
|
||||
|
||||
// RUN: %target-codesign %t/swift-structs-execution
|
||||
// RUN: %target-run %t/swift-structs-execution | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
#include <assert.h>
|
||||
#include "structs.h"
|
||||
|
||||
int main() {
|
||||
using namespace Structs;
|
||||
|
||||
static_assert(sizeof(StructOneI64) == 8, "");
|
||||
static_assert(sizeof(StructTwoI32) == 8, "");
|
||||
static_assert(sizeof(StructOneI16AndOneStruct) == 12, "");
|
||||
static_assert(sizeof(StructU16AndPointer) == (sizeof(void *) * 2), "");
|
||||
static_assert(sizeof(StructDoubleAndFloat) == 16, "");
|
||||
|
||||
StructOneI64 structOneI64 = returnNewStructOneI64();
|
||||
printStructOneI64(structOneI64);
|
||||
// CHECK: StructOneI64.x = 42
|
||||
|
||||
printStructOneI64(passThroughStructOneI64(structOneI64));
|
||||
// CHECK-NEXT: StructOneI64.x = 42
|
||||
|
||||
printStructTwoI32(passThroughStructTwoI32(1, returnNewStructTwoI32(5), 4));
|
||||
// CHECK-NEXT: StructTwoI32.x = 6, y = 14
|
||||
|
||||
printStructStructTwoI32_and_OneI16AndOneStruct(
|
||||
returnNewStructTwoI32(7), returnNewStructOneI16AndOneStruct());
|
||||
// CHECK-NEXT: StructTwoI32.x = 7, y = 14
|
||||
// CHECK-NEXT: StructOneI16AndOneStruct.x = 255, y.x = 5, y.y = 72
|
||||
|
||||
char c = 'A';
|
||||
auto structU16AndPointer = returnNewStructU16AndPointer(&c);
|
||||
assert(getStructU16AndPointer_x(structU16AndPointer) == 55);
|
||||
assert(getStructU16AndPointer_y(structU16AndPointer) == &c);
|
||||
|
||||
double doubleValue = 1.25;
|
||||
float floatValue = -5.0f;
|
||||
auto structDoubleAndFloat = returnNewStructDoubleAndFloat(floatValue, doubleValue);
|
||||
assert(getStructDoubleAndFloat_x(structDoubleAndFloat) == doubleValue);
|
||||
assert(getStructDoubleAndFloat_y(structDoubleAndFloat) == floatValue);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h
|
||||
// RUN: %FileCheck %s < %t/structs.h
|
||||
|
||||
// RUN: %check-interop-cxx-header-in-clang(%t/structs.h)
|
||||
|
||||
public struct StructOneI64 {
|
||||
let x: Int64
|
||||
}
|
||||
|
||||
public struct StructTwoI32 {
|
||||
let x, y: Int32
|
||||
}
|
||||
|
||||
public struct StructOneI16AndOneStruct {
|
||||
let x: Int16
|
||||
let y: StructTwoI32
|
||||
}
|
||||
|
||||
public struct StructU16AndPointer {
|
||||
let x: UInt8
|
||||
let y: UnsafeMutableRawPointer
|
||||
}
|
||||
|
||||
public struct StructDoubleAndFloat {
|
||||
let x: Double
|
||||
let y: Float
|
||||
}
|
||||
|
||||
// CHECK: class StructDoubleAndFloat final {
|
||||
|
||||
// CHECK: class StructOneI16AndOneStruct final {
|
||||
|
||||
// CHECK: class StructOneI64 final {
|
||||
|
||||
// CHECK: class StructTwoI32 final {
|
||||
|
||||
// CHECK: class StructU16AndPointer final {
|
||||
|
||||
public func returnNewStructOneI64() -> StructOneI64 { return StructOneI64(x: 42 ) }
|
||||
|
||||
public func passThroughStructOneI64(_ x: StructOneI64) -> StructOneI64 { return x }
|
||||
|
||||
public func printStructOneI64(_ x: StructOneI64) {
|
||||
print("StructOneI64.x = \(x.x)")
|
||||
}
|
||||
|
||||
public func returnNewStructTwoI32(_ x: Int32) -> StructTwoI32 { return StructTwoI32(x: x, y: x * 2) }
|
||||
|
||||
public func passThroughStructTwoI32(_ i: Int32, _ x: StructTwoI32, _ j: Int32) -> StructTwoI32 {
|
||||
return StructTwoI32(x: x.x + i, y: x.y + j)
|
||||
}
|
||||
|
||||
public func printStructTwoI32(_ x: StructTwoI32) {
|
||||
print("StructTwoI32.x = \(x.x), y = \(x.y)")
|
||||
}
|
||||
|
||||
public func returnNewStructOneI16AndOneStruct() -> StructOneI16AndOneStruct {
|
||||
return StructOneI16AndOneStruct(x: 0xFF, y: StructTwoI32(x: 5, y: 72))
|
||||
}
|
||||
|
||||
public func printStructStructTwoI32_and_OneI16AndOneStruct(_ y: StructTwoI32, _ x: StructOneI16AndOneStruct) {
|
||||
printStructTwoI32(y)
|
||||
print("StructOneI16AndOneStruct.x = \(x.x), y.x = \(x.y.x), y.y = \(x.y.y)")
|
||||
}
|
||||
|
||||
public func returnNewStructU16AndPointer(_ x: UnsafeMutableRawPointer) -> StructU16AndPointer {
|
||||
return StructU16AndPointer(x: 55, y: x)
|
||||
}
|
||||
|
||||
public func getStructU16AndPointer_x(_ x: StructU16AndPointer) -> UInt8 { return x.x }
|
||||
|
||||
public func getStructU16AndPointer_y(_ x: StructU16AndPointer) -> UnsafeMutableRawPointer { return x.y }
|
||||
|
||||
public func returnNewStructDoubleAndFloat(_ y: Float, _ x: Double) -> StructDoubleAndFloat {
|
||||
return StructDoubleAndFloat(x: x, y: y)
|
||||
}
|
||||
|
||||
public func getStructDoubleAndFloat_x(_ x: StructDoubleAndFloat) -> Double { return x.x }
|
||||
|
||||
public func getStructDoubleAndFloat_y(_ x: StructDoubleAndFloat) -> Float { return x.y }
|
||||
|
||||
// CHECK: inline double getStructDoubleAndFloat_x(const StructDoubleAndFloat& x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::$s7Structs25getStructDoubleAndFloat_xySdAA0cdeF0VF(_impl::swift_interop_passDirect_Structs_StructDoubleAndFloat(_impl::_impl_StructDoubleAndFloat::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline float getStructDoubleAndFloat_y(const StructDoubleAndFloat& x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::$s7Structs25getStructDoubleAndFloat_yySfAA0cdeF0VF(_impl::swift_interop_passDirect_Structs_StructDoubleAndFloat(_impl::_impl_StructDoubleAndFloat::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline uint8_t getStructU16AndPointer_x(const StructU16AndPointer& x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::$s7Structs24getStructU16AndPointer_xys5UInt8VAA0cdeF0VF(_impl::swift_interop_passDirect_Structs_StructU16AndPointer(_impl::_impl_StructU16AndPointer::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline void * _Nonnull getStructU16AndPointer_y(const StructU16AndPointer& x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::$s7Structs24getStructU16AndPointer_yySvAA0cdeF0VF(_impl::swift_interop_passDirect_Structs_StructU16AndPointer(_impl::_impl_StructU16AndPointer::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructOneI64 passThroughStructOneI64(const StructOneI64& x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructOneI64::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructOneI64(result, _impl::$s7Structs23passThroughStructOneI64yAA0deF0VADF(_impl::swift_interop_passDirect_Structs_StructOneI64(_impl::_impl_StructOneI64::getOpaquePointer(x))));
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructTwoI32 passThroughStructTwoI32(int32_t i, const StructTwoI32& x, int32_t j) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructTwoI32::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructTwoI32(result, _impl::$s7Structs23passThroughStructTwoI32yAA0deF0Vs5Int32V_AdFtF(i, _impl::swift_interop_passDirect_Structs_StructTwoI32(_impl::_impl_StructTwoI32::getOpaquePointer(x)), j));
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline void printStructOneI64(const StructOneI64& x) noexcept {
|
||||
// CHECK-NEXT: return _impl::$s7Structs17printStructOneI64yyAA0cdE0VF(_impl::swift_interop_passDirect_Structs_StructOneI64(_impl::_impl_StructOneI64::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline void printStructStructTwoI32_and_OneI16AndOneStruct(const StructTwoI32& y, const StructOneI16AndOneStruct& x) noexcept {
|
||||
// CHECK-NEXT: return _impl::$s7Structs011printStructc20TwoI32_and_OneI16AndgC0yyAA0cdE0V_AA0cghigC0VtF(_impl::swift_interop_passDirect_Structs_StructTwoI32(_impl::_impl_StructTwoI32::getOpaquePointer(y)), _impl::swift_interop_passDirect_Structs_StructOneI16AndOneStruct(_impl::_impl_StructOneI16AndOneStruct::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline void printStructTwoI32(const StructTwoI32& x) noexcept {
|
||||
// CHECK-NEXT: return _impl::$s7Structs17printStructTwoI32yyAA0cdE0VF(_impl::swift_interop_passDirect_Structs_StructTwoI32(_impl::_impl_StructTwoI32::getOpaquePointer(x)));
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructDoubleAndFloat returnNewStructDoubleAndFloat(float y, double x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructDoubleAndFloat::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructDoubleAndFloat(result, _impl::$s7Structs29returnNewStructDoubleAndFloatyAA0defG0VSf_SdtF(y, x));
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructOneI16AndOneStruct returnNewStructOneI16AndOneStruct() noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructOneI16AndOneStruct::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructOneI16AndOneStruct(result, _impl::$s7Structs024returnNewStructOneI16AndeD0AA0defgeD0VyF());
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructOneI64 returnNewStructOneI64() noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructOneI64::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructOneI64(result, _impl::$s7Structs21returnNewStructOneI64AA0deF0VyF());
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructTwoI32 returnNewStructTwoI32(int32_t x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructTwoI32::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructTwoI32(result, _impl::$s7Structs21returnNewStructTwoI32yAA0deF0Vs5Int32VF(x));
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: inline StructU16AndPointer returnNewStructU16AndPointer(void * _Nonnull x) noexcept SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return _impl::_impl_StructU16AndPointer::returnNewValue([&](char * _Nonnull result) {
|
||||
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_StructU16AndPointer(result, _impl::$s7Structs28returnNewStructU16AndPointeryAA0defG0VSvF(x));
|
||||
// CHECK-NEXT: });
|
||||
// CHECK-NEXT: }
|
||||
@@ -5,11 +5,42 @@
|
||||
// RUN: %check-interop-cxx-header-in-clang(%t/structs.h -Wno-unused-private-field)
|
||||
|
||||
// CHECK: namespace Structs {
|
||||
// CHECK: namespace _impl {
|
||||
|
||||
// CHECK: namespace Structs {
|
||||
|
||||
// CHECK: namespace _impl {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: class _impl_StructWithIntField;
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: class StructWithIntField final {
|
||||
// CHECK-NEXT: private:
|
||||
// CHECK-NEXT: inline StructWithIntField() {}
|
||||
// CHECK-NEXT: static inline StructWithIntField _make() { return StructWithIntField(); }
|
||||
// CHECK-NEXT: inline const char * _Nonnull _getOpaquePointer() const { return _storage; }
|
||||
// CHECK-NEXT: inline char * _Nonnull _getOpaquePointer() { return _storage; }
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: alignas(8) char _storage[8];
|
||||
// CHECK-NEXT: friend class _impl::_impl_StructWithIntField;
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK: namespace _impl {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: class _impl_StructWithIntField {
|
||||
// CHECK-NEXT: public:
|
||||
// CHECK-NEXT: static inline char * _Nonnull getOpaquePointer(StructWithIntField &object) { return object._getOpaquePointer(); }
|
||||
// CHECK-NEXT: static inline const char * _Nonnull getOpaquePointer(const StructWithIntField &object) { return object._getOpaquePointer(); }
|
||||
// CHECK-NEXT: template<class T>
|
||||
// CHECK-NEXT: static inline StructWithIntField returnNewValue(T callable) {
|
||||
// CHECK-NEXT: auto result = StructWithIntField::_make();
|
||||
// CHECK-NEXT: callable(result._getOpaquePointer());
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }
|
||||
public struct StructWithIntField {
|
||||
let field: Int64
|
||||
}
|
||||
@@ -17,6 +48,7 @@ public struct StructWithIntField {
|
||||
// Special name gets renamed in C++.
|
||||
// CHECK: class register_ final {
|
||||
// CHECK: alignas(8) char _storage[16];
|
||||
// CHECK-NEXT: friend class
|
||||
// CHECK-NEXT: };
|
||||
public struct register {
|
||||
let field1: Int64
|
||||
|
||||
@@ -29,11 +29,11 @@ config.substitutions.insert(0, ('%target-interop-build-clangxx', '%target-clangx
|
||||
|
||||
# Test parsing of the generated C++ header in different C++ language modes.
|
||||
config.substitutions.insert(0, ('%check-interop-cxx-header-in-clang\(([^)]+)\)',
|
||||
SubstituteCaptures(r'%check-cxx-header-in-clang -std=c++14 \1 && '
|
||||
r'%check-cxx-header-in-clang -std=c++17 \1 && '
|
||||
r'%check-cxx-header-in-clang -std=c++20 \1')))
|
||||
SubstituteCaptures(r'%check-cxx-header-in-clang -std=c++14 -Wno-padded -Wno-c11-extensions \1 && '
|
||||
r'%check-cxx-header-in-clang -std=c++17 -Wno-padded -Wno-c11-extensions \1 && '
|
||||
r'%check-cxx-header-in-clang -std=c++20 -Wno-padded -Wno-c11-extensions \1')))
|
||||
|
||||
# Test parsing of the generated C header in different C language modes.
|
||||
config.substitutions.insert(0, ('%check-interop-c-header-in-clang\(([^)]+)\)',
|
||||
SubstituteCaptures(r'%check-c-header-in-clang -std=c99 \1 && '
|
||||
r'%check-c-header-in-clang -std=c11 \1')))
|
||||
SubstituteCaptures(r'%check-c-header-in-clang -std=c99 -Wno-padded -Wno-c11-extensions \1 && '
|
||||
r'%check-c-header-in-clang -std=c11 -Wno-padded \1')))
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
// CHECK-NEXT: #include <cstdint>
|
||||
// CHECK-NEXT: #include <cstddef>
|
||||
// CHECK-NEXT: #include <cstdbool>
|
||||
// CHECK-NEXT: #include <cstring>
|
||||
// CHECK-NEXT: #else
|
||||
// CHECK-NEXT: #include <stdint.h>
|
||||
// CHECK-NEXT: #include <stddef.h>
|
||||
// CHECK-NEXT: #include <stdbool.h>
|
||||
// CHECK-NEXT: #include <string.h>
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
// CHECK-LABEL: !defined(SWIFT_TYPEDEFS)
|
||||
|
||||
Reference in New Issue
Block a user