Skip to content

Commit 0e20f76

Browse files
committed
Add cxx_virtual_method instruction.
1 parent c3b98ef commit 0e20f76

24 files changed

+369
-86
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,14 @@ class SILBuilder {
14721472
getSILDebugLocation(Loc), Operand, Member, MethodTy));
14731473
}
14741474

1475+
CXXVirtualMethodInst *createCXXVirtualMethod(SILLocation Loc,
1476+
SILValue Operand,
1477+
SILDeclRef Member,
1478+
SILType MethodTy) {
1479+
return insert(CXXVirtualMethodInst::create(getSILDebugLocation(Loc),
1480+
Operand, Member, MethodTy));
1481+
}
1482+
14751483
WitnessMethodInst *createWitnessMethod(SILLocation Loc, CanType LookupTy,
14761484
ProtocolConformanceRef Conformance,
14771485
SILDeclRef Member, SILType MethodTy) {

include/swift/SIL/SILCloner.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,17 @@ SILCloner<ImplClass>::visitObjCSuperMethodInst(ObjCSuperMethodInst *Inst) {
20232023
Inst->getMember(), Inst->getType()));
20242024
}
20252025

2026+
template <typename ImplClass>
2027+
void SILCloner<ImplClass>::visitCXXVirtualMethodInst(
2028+
CXXVirtualMethodInst *Inst) {
2029+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2030+
recordClonedInstruction(
2031+
Inst,
2032+
getBuilder().createCXXVirtualMethod(
2033+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
2034+
Inst->getMember(), getOpType(Inst->getExtractedMethod()->getType())));
2035+
}
2036+
20262037
template<typename ImplClass>
20272038
void
20282039
SILCloner<ImplClass>::visitWitnessMethodInst(WitnessMethodInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5881,6 +5881,66 @@ class ObjCSuperMethodInst
58815881
: UnaryInstructionBase(DebugLoc, Operand, Ty, Member) {}
58825882
};
58835883

5884+
/// This is either the extracted method or the adjusted this ptr that
5885+
/// is the result of a CXXVirtualMethodInst.
5886+
class CXXVirtualMethodInst;
5887+
class CXXVirtualMethodResult final : public MultipleValueInstructionResult {
5888+
public:
5889+
CXXVirtualMethodResult(unsigned index, SILType type,
5890+
ValueOwnershipKind ownershipKind)
5891+
: MultipleValueInstructionResult(ValueKind::CXXVirtualMethodResult, index,
5892+
type, ownershipKind) {}
5893+
5894+
CXXVirtualMethodInst *getParent(); // inline below
5895+
const CXXVirtualMethodInst *getParent() const {
5896+
return const_cast<CXXVirtualMethodResult *>(this)->getParent();
5897+
}
5898+
5899+
bool isExtractedMethod() const { return getIndex() == 0; }
5900+
bool isAdjustedThisPtr() const { return getIndex() == 1; }
5901+
5902+
static bool classof(const SILNode *N) {
5903+
return N->getKind() == SILNodeKind::CXXVirtualMethodResult;
5904+
}
5905+
};
5906+
5907+
/// Represents looking up a virtual method from a c++ virtual method table and
5908+
/// adjusting the this pointer.
5909+
class CXXVirtualMethodInst final
5910+
: public UnaryInstructionBase<SILInstructionKind::CXXVirtualMethodInst,
5911+
MultipleValueInstruction>,
5912+
public MultipleValueInstructionTrailingObjects<CXXVirtualMethodInst,
5913+
CXXVirtualMethodResult> {
5914+
SILDeclRef Member;
5915+
friend SILBuilder;
5916+
5917+
template <class, class...> friend class llvm::TrailingObjects;
5918+
using MultipleValueInstructionTrailingObjects::numTrailingObjects;
5919+
5920+
using MultipleValueInstructionTrailingObjects::getTrailingObjects;
5921+
5922+
CXXVirtualMethodInst(SILDebugLocation debugLoc, SILValue ThisPtr,
5923+
SILDeclRef Member, SILType Ty);
5924+
5925+
static CXXVirtualMethodInst *create(SILDebugLocation debugLoc,
5926+
SILValue ThisPtr, SILDeclRef Member,
5927+
SILType Ty);
5928+
5929+
public:
5930+
using MultipleValueInstructionTrailingObjects::totalSizeToAlloc;
5931+
5932+
SILDeclRef getMember() const { return Member; }
5933+
5934+
SILValue getExtractedMethod() const { return &getAllResultsBuffer().front(); }
5935+
5936+
SILValue getAdjustedThisPtr() const { return &getAllResultsBuffer().back(); }
5937+
};
5938+
5939+
inline CXXVirtualMethodInst *CXXVirtualMethodResult::getParent() {
5940+
auto *Parent = MultipleValueInstructionResult::getParent();
5941+
return cast<CXXVirtualMethodInst>(Parent);
5942+
}
5943+
58845944
/// WitnessMethodInst - Given a type, a protocol conformance,
58855945
/// and a protocol method constant, extracts the implementation of that method
58865946
/// for the type.

include/swift/SIL/SILNodes.def

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ ABSTRACT_VALUE(MultipleValueInstructionResult, ValueBase)
415415
MULTIPLE_VALUE_INST_RESULT(BeginApplyResult, MultipleValueInstructionResult)
416416
MULTIPLE_VALUE_INST_RESULT(DestructureStructResult, MultipleValueInstructionResult)
417417
MULTIPLE_VALUE_INST_RESULT(DestructureTupleResult, MultipleValueInstructionResult)
418-
VALUE_RANGE(MultipleValueInstructionResult, BeginApplyResult, DestructureTupleResult)
418+
MULTIPLE_VALUE_INST_RESULT(CXXVirtualMethodResult, MultipleValueInstructionResult)
419+
VALUE_RANGE(MultipleValueInstructionResult, BeginApplyResult, CXXVirtualMethodResult)
419420

420421
VALUE(SILUndef, ValueBase)
421422

@@ -855,10 +856,12 @@ MULTIPLE_VALUE_INST(DestructureStructInst, destructure_struct,
855856
MultipleValueInstruction, None, DoesNotRelease)
856857
MULTIPLE_VALUE_INST(DestructureTupleInst, destructure_tuple,
857858
MultipleValueInstruction, None, DoesNotRelease)
858-
INST_RANGE(MultipleValueInstruction, BeginApplyInst, DestructureTupleInst)
859+
MULTIPLE_VALUE_INST(CXXVirtualMethodInst, cxx_virtual_method,
860+
MultipleValueInstruction, None, DoesNotRelease)
861+
INST_RANGE(MultipleValueInstruction, BeginApplyInst, CXXVirtualMethodInst)
859862

860-
NODE_RANGE(SILInstruction, AllocStackInst, DestructureTupleInst)
861-
NODE_RANGE(SILNode, SILPhiArgument, DestructureTupleInst)
863+
NODE_RANGE(SILInstruction, AllocStackInst, CXXVirtualMethodInst)
864+
NODE_RANGE(SILNode, SILPhiArgument, CXXVirtualMethodInst)
862865

863866
#undef SINGLE_VALUE_INST_RANGE
864867
#undef INST_RANGE

lib/IRGen/GenCall.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ namespace {
247247
/// function type.
248248
void expandCoroutineContinuationType();
249249

250-
Signature getSignature();
250+
Signature getSignature(llvm::FunctionType *llvmType = nullptr);
251251

252252
private:
253253
void expand(SILParameterInfo param);
@@ -1424,10 +1424,11 @@ void SignatureExpansion::expandCoroutineContinuationType() {
14241424
expandCoroutineContinuationParameters();
14251425
}
14261426

1427-
Signature SignatureExpansion::getSignature() {
1427+
Signature SignatureExpansion::getSignature(llvm::FunctionType *llvmType) {
14281428
// Create the appropriate LLVM type.
1429-
llvm::FunctionType *llvmType =
1430-
llvm::FunctionType::get(ResultIRType, ParamIRTypes, /*variadic*/ false);
1429+
if (!llvmType)
1430+
llvmType =
1431+
llvm::FunctionType::get(ResultIRType, ParamIRTypes, /*variadic*/ false);
14311432

14321433
assert((ForeignInfo.ClangInfo != nullptr) ==
14331434
(FnType->getLanguage() == SILFunctionLanguage::C) &&
@@ -1470,6 +1471,17 @@ Signature Signature::forCoroutineContinuation(IRGenModule &IGM,
14701471
return expansion.getSignature();
14711472
}
14721473

1474+
Signature Signature::forCXXMethod(IRGenModule &IGM,
1475+
const clang::CXXMethodDecl *decl,
1476+
CanSILFunctionType fnType) {
1477+
SignatureExpansion expansion(IGM, fnType);
1478+
expansion.ForeignInfo.ClangInfo =
1479+
&clang::CodeGen::arrangeCXXMethodDeclaration(IGM.getClangCGM(), decl);
1480+
llvm::FunctionType *Ty = clang::CodeGen::getFunctionType(
1481+
IGM.getClangCGM(), *expansion.ForeignInfo.ClangInfo);
1482+
return expansion.getSignature(Ty);
1483+
}
1484+
14731485
void irgen::extractScalarResults(IRGenFunction &IGF, llvm::Type *bodyType,
14741486
llvm::Value *call, Explosion &out) {
14751487
assert(!bodyType->isVoidTy() && "Unexpected void result type!");

lib/IRGen/IRGenSIL.cpp

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,43 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#define DEBUG_TYPE "irgensil"
19-
#include "llvm/IR/DIBuilder.h"
20-
#include "llvm/IR/Function.h"
21-
#include "llvm/IR/Module.h"
22-
#include "llvm/IR/Instructions.h"
23-
#include "llvm/IR/IntrinsicInst.h"
24-
#include "llvm/IR/InlineAsm.h"
25-
#include "llvm/IR/Intrinsics.h"
26-
#include "llvm/ADT/MapVector.h"
27-
#include "llvm/ADT/SmallBitVector.h"
28-
#include "llvm/ADT/TinyPtrVector.h"
29-
#include "llvm/Support/SaveAndRestore.h"
30-
#include "llvm/Support/Debug.h"
31-
#include "llvm/Transforms/Utils/Local.h"
32-
#include "clang/AST/ASTContext.h"
33-
#include "clang/Basic/TargetInfo.h"
34-
#include "swift/Basic/ExternalUnion.h"
35-
#include "swift/Basic/Range.h"
36-
#include "swift/Basic/STLExtras.h"
3719
#include "swift/AST/ASTContext.h"
3820
#include "swift/AST/IRGenOptions.h"
39-
#include "swift/AST/Pattern.h"
4021
#include "swift/AST/ParameterList.h"
22+
#include "swift/AST/Pattern.h"
4123
#include "swift/AST/SubstitutionMap.h"
4224
#include "swift/AST/Types.h"
25+
#include "swift/Basic/ExternalUnion.h"
26+
#include "swift/Basic/Range.h"
27+
#include "swift/Basic/STLExtras.h"
4328
#include "swift/SIL/ApplySite.h"
4429
#include "swift/SIL/Dominance.h"
30+
#include "swift/SIL/InstructionUtils.h"
4531
#include "swift/SIL/PrettyStackTrace.h"
4632
#include "swift/SIL/SILDebugScope.h"
4733
#include "swift/SIL/SILDeclRef.h"
4834
#include "swift/SIL/SILLinkage.h"
4935
#include "swift/SIL/SILModule.h"
5036
#include "swift/SIL/SILType.h"
5137
#include "swift/SIL/SILVisitor.h"
52-
#include "swift/SIL/InstructionUtils.h"
38+
#include "clang/AST/ASTContext.h"
39+
#include "clang/AST/DeclCXX.h"
40+
#include "clang/Basic/TargetInfo.h"
5341
#include "clang/CodeGen/CodeGenABITypes.h"
42+
#include "clang/CodeGen/SwiftCallingConv.h"
43+
#include "llvm/ADT/MapVector.h"
44+
#include "llvm/ADT/SmallBitVector.h"
45+
#include "llvm/ADT/TinyPtrVector.h"
46+
#include "llvm/IR/DIBuilder.h"
47+
#include "llvm/IR/Function.h"
48+
#include "llvm/IR/InlineAsm.h"
49+
#include "llvm/IR/Instructions.h"
50+
#include "llvm/IR/IntrinsicInst.h"
51+
#include "llvm/IR/Intrinsics.h"
52+
#include "llvm/IR/Module.h"
53+
#include "llvm/Support/Debug.h"
54+
#include "llvm/Support/SaveAndRestore.h"
55+
#include "llvm/Transforms/Utils/Local.h"
5456

5557
#include "CallEmission.h"
5658
#include "Explosion.h"
@@ -990,6 +992,7 @@ class IRGenSILFunction :
990992
void visitSuperMethodInst(SuperMethodInst *i);
991993
void visitObjCMethodInst(ObjCMethodInst *i);
992994
void visitObjCSuperMethodInst(ObjCSuperMethodInst *i);
995+
void visitCXXVirtualMethodInst(CXXVirtualMethodInst *i);
993996
void visitWitnessMethodInst(WitnessMethodInst *i);
994997

995998
void visitAllocValueBufferInst(AllocValueBufferInst *i);
@@ -5589,6 +5592,26 @@ void IRGenSILFunction::visitObjCMethodInst(swift::ObjCMethodInst *i) {
55895592
setLoweredObjCMethod(i, i->getMember());
55905593
}
55915594

5595+
void IRGenSILFunction::visitCXXVirtualMethodInst(CXXVirtualMethodInst *i) {
5596+
auto *cxxMethod = cast<clang::CXXMethodDecl>(
5597+
i->getMember().getAbstractFunctionDecl()->getClangDecl());
5598+
5599+
auto signature = Signature::forCXXMethod(
5600+
IGM, cxxMethod,
5601+
i->getExtractedMethod()->getType().castTo<SILFunctionType>());
5602+
5603+
auto selfAddress = getLoweredAddress(i->getOperand());
5604+
llvm::Value *self = selfAddress.getAddress();
5605+
5606+
auto *result = clang::CodeGen::swiftcall::lowerCXXVirtualMethodDeclReference(
5607+
IGM.getClangCGM(), cxxMethod, self,
5608+
selfAddress.getAlignment().asCharUnits(), signature.getType(), &Builder);
5609+
5610+
setLoweredValue(i->getExtractedMethod(), FunctionPointer(result, signature));
5611+
selfAddress = Address(self, selfAddress.getAlignment());
5612+
setLoweredAddress(i->getAdjustedThisPtr(), selfAddress);
5613+
}
5614+
55925615
void IRGenModule::emitSILStaticInitializers() {
55935616
SmallVector<SILFunction *, 8> StaticInitializers;
55945617
for (SILGlobalVariable &Global : getSILModule().getSILGlobals()) {

lib/IRGen/Signature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace clang {
3131
namespace CodeGen {
3232
class CGFunctionInfo;
3333
}
34+
class CXXMethodDecl;
3435
}
3536

3637
namespace swift {
@@ -126,6 +127,11 @@ class Signature {
126127
static Signature forCoroutineContinuation(IRGenModule &IGM,
127128
CanSILFunctionType coroType);
128129

130+
/// Compute the singature of a C++ method.
131+
static Signature forCXXMethod(IRGenModule &IGM,
132+
const clang::CXXMethodDecl *decl,
133+
CanSILFunctionType fnType);
134+
129135
llvm::FunctionType *getType() const {
130136
assert(isValid());
131137
return Type;

lib/ParseSIL/ParseSIL.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4243,6 +4243,7 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
42434243
case SILInstructionKind::ClassMethodInst:
42444244
case SILInstructionKind::SuperMethodInst:
42454245
case SILInstructionKind::ObjCMethodInst:
4246+
case SILInstructionKind::CXXVirtualMethodInst:
42464247
case SILInstructionKind::ObjCSuperMethodInst: {
42474248
SILDeclRef Member;
42484249
SILType MethodTy;
@@ -4274,6 +4275,9 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
42744275
case SILInstructionKind::ObjCSuperMethodInst:
42754276
ResultVal = B.createObjCSuperMethod(InstLoc, Val, Member, MethodTy);
42764277
break;
4278+
case SILInstructionKind::CXXVirtualMethodInst:
4279+
ResultVal = B.createCXXVirtualMethod(InstLoc, Val, Member, MethodTy);
4280+
break;
42774281
}
42784282
break;
42794283
}

lib/SIL/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP_OR_METATYPE(MustBeLive, ClassMethod)
280280
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP_OR_METATYPE(MustBeLive, ObjCMethod)
281281
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP_OR_METATYPE(MustBeLive, ObjCSuperMethod)
282282
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP_OR_METATYPE(MustBeLive, SuperMethod)
283+
ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP_OR_METATYPE(MustBeLive, CXXVirtualMethod)
283284
#undef ACCEPTS_ANY_NONTRIVIAL_OWNERSHIP_OR_METATYPE
284285

285286
// Trivial if trivial typed, otherwise must accept owned?

lib/SIL/SILDeclRef.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,21 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/SIL/SILDeclRef.h"
14-
#include "swift/SIL/SILLocation.h"
15-
#include "swift/AST/AnyFunctionRef.h"
1614
#include "swift/AST/ASTContext.h"
1715
#include "swift/AST/ASTMangler.h"
16+
#include "swift/AST/AnyFunctionRef.h"
1817
#include "swift/AST/Initializer.h"
1918
#include "swift/AST/ParameterList.h"
2019
#include "swift/ClangImporter/ClangImporter.h"
2120
#include "swift/ClangImporter/ClangModule.h"
2221
#include "swift/SIL/SILLinkage.h"
23-
#include "llvm/Support/Compiler.h"
24-
#include "llvm/Support/raw_ostream.h"
22+
#include "swift/SIL/SILLocation.h"
2523
#include "clang/AST/Attr.h"
2624
#include "clang/AST/Decl.h"
25+
#include "clang/AST/DeclCXX.h"
2726
#include "clang/AST/DeclObjC.h"
27+
#include "llvm/Support/Compiler.h"
28+
#include "llvm/Support/raw_ostream.h"
2829
using namespace swift;
2930

3031
/// Get the method dispatch mechanism for a method.
@@ -34,6 +35,13 @@ swift::getMethodDispatch(AbstractFunctionDecl *method) {
3435
if (method->hasForcedStaticDispatch())
3536
return MethodDispatch::Static;
3637

38+
if (auto *mdecl =
39+
dyn_cast_or_null<clang::CXXMethodDecl>(method->getClangDecl())) {
40+
if (mdecl->isVirtual()) {
41+
return MethodDispatch::Class;
42+
}
43+
}
44+
3745
// Import-as-member declarations are always statically referenced.
3846
if (method->isImportAsMember())
3947
return MethodDispatch::Static;

lib/SIL/SILInstructions.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,28 @@ ObjCMethodInst::create(SILDebugLocation DebugLoc, SILValue Operand,
17151715
Member, Ty);
17161716
}
17171717

1718+
CXXVirtualMethodInst::CXXVirtualMethodInst(SILDebugLocation DebugLoc,
1719+
SILValue Operand, SILDeclRef Member,
1720+
SILType Ty)
1721+
: UnaryInstructionBase(DebugLoc, Operand),
1722+
MultipleValueInstructionTrailingObjects(
1723+
this, {Ty, Operand->getType()},
1724+
{ /* extracted method */ ValueOwnershipKind::Any,
1725+
/* adjusted this */ ValueOwnershipKind::Any}),
1726+
Member(Member) {}
1727+
1728+
CXXVirtualMethodInst *CXXVirtualMethodInst::create(SILDebugLocation DebugLoc,
1729+
SILValue Operand,
1730+
SILDeclRef Member,
1731+
SILType Ty) {
1732+
SILModule *Mod = Operand->getModule();
1733+
unsigned size =
1734+
totalSizeToAlloc<MultipleValueInstruction *, CXXVirtualMethodResult>(1,
1735+
2);
1736+
void *Buffer = Mod->allocateInst(size, alignof(CXXVirtualMethodInst));
1737+
return ::new (Buffer) CXXVirtualMethodInst(DebugLoc, Operand, Member, Ty);
1738+
}
1739+
17181740
InitExistentialAddrInst *InitExistentialAddrInst::create(
17191741
SILDebugLocation Loc, SILValue Existential, CanType ConcreteType,
17201742
SILType ConcreteLoweredType, ArrayRef<ProtocolConformanceRef> Conformances,

lib/SIL/SILPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,12 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
16931693
*this << ", ";
16941694
*this << AMI->getType();
16951695
}
1696+
void visitCXXVirtualMethodInst(CXXVirtualMethodInst *CXXVMI) {
1697+
*this << getIDAndType(CXXVMI->getOperand()) << ", " << CXXVMI->getMember();
1698+
*this << " : " << CXXVMI->getMember().getDecl()->getInterfaceType();
1699+
*this << ", ";
1700+
*this << CXXVMI->getExtractedMethod()->getType();
1701+
}
16961702
void visitWitnessMethodInst(WitnessMethodInst *WMI) {
16971703
PrintOptions QualifiedSILTypeOptions =
16981704
PrintOptions::printQualifiedSILType();

0 commit comments

Comments
 (0)