|
20 | 20 | #include "swift/AST/Decl.h"
|
21 | 21 | #include "swift/AST/IRGenOptions.h"
|
22 | 22 | #include "swift/AST/Pattern.h"
|
| 23 | +#include "swift/AST/SemanticAttrs.h" |
23 | 24 | #include "swift/AST/SubstitutionMap.h"
|
24 | 25 | #include "swift/AST/Types.h"
|
25 | 26 | #include "swift/IRGen/Linking.h"
|
| 27 | +#include "swift/SIL/SILFunctionBuilder.h" |
26 | 28 | #include "swift/SIL/SILModule.h"
|
27 | 29 | #include "clang/AST/ASTContext.h"
|
28 | 30 | #include "clang/AST/Attr.h"
|
|
36 | 38 | #include "llvm/IR/DerivedTypes.h"
|
37 | 39 | #include "llvm/IR/Function.h"
|
38 | 40 |
|
| 41 | +#include "GenDecl.h" |
39 | 42 | #include "GenMeta.h"
|
40 | 43 | #include "GenRecord.h"
|
41 | 44 | #include "GenType.h"
|
42 | 45 | #include "IRGenFunction.h"
|
43 | 46 | #include "IRGenModule.h"
|
44 | 47 | #include "IndirectTypeInfo.h"
|
45 | 48 | #include "MemberAccessStrategy.h"
|
| 49 | +#include "MetadataLayout.h" |
46 | 50 | #include "NonFixedTypeInfo.h"
|
47 | 51 | #include "ResilientTypeInfo.h"
|
| 52 | +#include "Signature.h" |
48 | 53 | #include "StructMetadataVisitor.h"
|
49 |
| -#include "MetadataLayout.h" |
50 | 54 |
|
51 | 55 | #pragma clang diagnostic ignored "-Winconsistent-missing-override"
|
52 | 56 |
|
@@ -326,6 +330,7 @@ namespace {
|
326 | 330 | public StructTypeInfoBase<LoadableClangRecordTypeInfo, LoadableTypeInfo,
|
327 | 331 | ClangFieldInfo> {
|
328 | 332 | const clang::RecordDecl *ClangDecl;
|
| 333 | + |
329 | 334 | public:
|
330 | 335 | LoadableClangRecordTypeInfo(ArrayRef<ClangFieldInfo> fields,
|
331 | 336 | unsigned explosionSize,
|
@@ -374,6 +379,73 @@ namespace {
|
374 | 379 | ClangFieldInfo> {
|
375 | 380 | const clang::RecordDecl *ClangDecl;
|
376 | 381 |
|
| 382 | + const clang::CXXConstructorDecl *findCopyConstructor() const { |
| 383 | + const clang::CXXRecordDecl *cxxRecordDecl = |
| 384 | + dyn_cast<clang::CXXRecordDecl>(ClangDecl); |
| 385 | + if (!cxxRecordDecl) |
| 386 | + return nullptr; |
| 387 | + for (auto method : cxxRecordDecl->methods()) { |
| 388 | + if (auto ctor = dyn_cast<clang::CXXConstructorDecl>(method)) { |
| 389 | + if (ctor->isCopyConstructor()) |
| 390 | + return ctor; |
| 391 | + } |
| 392 | + } |
| 393 | + return nullptr; |
| 394 | + } |
| 395 | + |
| 396 | + CanSILFunctionType createCXXCopyConstructorFunctionType(IRGenFunction &IGF, |
| 397 | + SILType T) const { |
| 398 | + // Create the following function type: |
| 399 | + // @convention(c) (UnsafePointer<T>) -> @out T |
| 400 | + // This is how clang *would* import the copy constructor. So, later, when |
| 401 | + // we pass it to "emitCXXConstructorThunkIfNeeded" we get a thunk with |
| 402 | + // the following LLVM function type: |
| 403 | + // void (%struct.T* %this, %struct.T* %0) |
| 404 | + auto ptrTypeDecl = |
| 405 | + IGF.getSILModule().getASTContext().getUnsafePointerDecl(); |
| 406 | + auto subst = SubstitutionMap::get(ptrTypeDecl->getGenericSignature(), |
| 407 | + {T.getASTType()}, |
| 408 | + ArrayRef<ProtocolConformanceRef>{}); |
| 409 | + auto ptrType = ptrTypeDecl->getDeclaredInterfaceType().subst(subst); |
| 410 | + SILParameterInfo ptrParam(ptrType->getCanonicalType(), |
| 411 | + ParameterConvention::Direct_Unowned); |
| 412 | + SILResultInfo result(T.getASTType(), ResultConvention::Indirect); |
| 413 | + |
| 414 | + return SILFunctionType::get( |
| 415 | + GenericSignature(), |
| 416 | + SILFunctionType::ExtInfo().withRepresentation( |
| 417 | + SILFunctionTypeRepresentation::CFunctionPointer), |
| 418 | + SILCoroutineKind::None, |
| 419 | + /*callee=*/ParameterConvention::Direct_Unowned, |
| 420 | + /*params*/ {ptrParam}, |
| 421 | + /*yields*/ {}, /*results*/ {result}, |
| 422 | + /*error*/ None, |
| 423 | + /*pattern subs*/ SubstitutionMap(), |
| 424 | + /*invocation subs*/ SubstitutionMap(), IGF.IGM.Context); |
| 425 | + } |
| 426 | + |
| 427 | + void emitCopyWithCopyConstructor( |
| 428 | + IRGenFunction &IGF, SILType T, |
| 429 | + const clang::CXXConstructorDecl *copyConstructor, llvm::Value *src, |
| 430 | + llvm::Value *dest) const { |
| 431 | + auto fnType = createCXXCopyConstructorFunctionType(IGF, T); |
| 432 | + auto globalDecl = |
| 433 | + clang::GlobalDecl(copyConstructor, clang::Ctor_Complete); |
| 434 | + auto clangFnAddr = |
| 435 | + IGF.IGM.getAddrOfClangGlobalDecl(globalDecl, NotForDefinition); |
| 436 | + auto callee = cast<llvm::Function>(clangFnAddr->stripPointerCasts()); |
| 437 | + Signature signature = IGF.IGM.getSignature(fnType); |
| 438 | + std::string name = "__swift_cxx_copy_ctor" + callee->getName().str(); |
| 439 | + clangFnAddr = emitCXXConstructorThunkIfNeeded( |
| 440 | + IGF.IGM, signature, copyConstructor, name, clangFnAddr); |
| 441 | + callee = cast<llvm::Function>(clangFnAddr); |
| 442 | + dest = IGF.coerceValue(dest, callee->getFunctionType()->getParamType(0), |
| 443 | + IGF.IGM.DataLayout); |
| 444 | + src = IGF.coerceValue(src, callee->getFunctionType()->getParamType(1), |
| 445 | + IGF.IGM.DataLayout); |
| 446 | + IGF.Builder.CreateCall(callee, {dest, src}); |
| 447 | + } |
| 448 | + |
377 | 449 | public:
|
378 | 450 | AddressOnlyClangRecordTypeInfo(ArrayRef<ClangFieldInfo> fields,
|
379 | 451 | llvm::Type *storageType, Size size,
|
@@ -451,6 +523,21 @@ namespace {
|
451 | 523 | "member functions.");
|
452 | 524 | }
|
453 | 525 |
|
| 526 | + void initializeWithCopy(IRGenFunction &IGF, Address destAddr, |
| 527 | + Address srcAddr, SILType T, |
| 528 | + bool isOutlined) const override { |
| 529 | + if (auto copyConstructor = findCopyConstructor()) { |
| 530 | + emitCopyWithCopyConstructor(IGF, T, copyConstructor, |
| 531 | + srcAddr.getAddress(), |
| 532 | + destAddr.getAddress()); |
| 533 | + return; |
| 534 | + } |
| 535 | + StructTypeInfoBase<AddressOnlyClangRecordTypeInfo, FixedTypeInfo, |
| 536 | + ClangFieldInfo>::initializeWithCopy(IGF, destAddr, |
| 537 | + srcAddr, T, |
| 538 | + isOutlined); |
| 539 | + } |
| 540 | + |
454 | 541 | llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const { return None; }
|
455 | 542 | llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF, SILType T) const {
|
456 | 543 | return None;
|
|
0 commit comments