Skip to content

Commit e422b29

Browse files
authored
Merge pull request #1227 from swiftwasm/master
[pull] swiftwasm from master
2 parents d1bd3e2 + 26f7823 commit e422b29

37 files changed

+388
-98
lines changed

docs/WindowsBuild.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ git clone https://github.com/compnerd/swift-build swift-build
7979
## Acquire ICU, SQLite3, curl, libxml2 and zlib
8080

8181
```
82-
python -m pip install --user msrest azure-devops tabulate
83-
python swift-build\utilities\swift-build.py --build-id ICU --latest-artifacts --filter windows-x64 --download
84-
python swift-build\utilities\swift-build.py --build-id XML2 --latest-artifacts --filter windows-x64 --download
85-
python swift-build\utilities\swift-build.py --build-id CURL --latest-artifacts --filter windows-x64 --download
86-
python swift-build\utilities\swift-build.py --build-id zlib --latest-artifacts --filter windows-x64 --download
87-
python swift-build\utilities\swift-build.py --build-id SQLite --latest-artifacts --filter windows-x64 --download
82+
C:\Python27\python.exe -m pip install --user msrest azure-devops tabulate
83+
C:\Python27\python.exe swift-build\utilities\swift-build.py --build-id ICU --latest-artifacts --filter windows-x64 --download
84+
C:\Python27\python.exe swift-build\utilities\swift-build.py --build-id XML2 --latest-artifacts --filter windows-x64 --download
85+
C:\Python27\python.exe swift-build\utilities\swift-build.py --build-id CURL --latest-artifacts --filter windows-x64 --download
86+
C:\Python27\python.exe swift-build\utilities\swift-build.py --build-id zlib --latest-artifacts --filter windows-x64 --download
87+
C:\Python27\python.exe swift-build\utilities\swift-build.py --build-id SQLite --latest-artifacts --filter windows-x64 --download
8888
```
8989

9090
Extract the zip files, ignoring the top level directory, into `S:/Library`. The directory structure should resemble:

include/swift/SIL/SILModule.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ class SILModule {
595595
bool deserializeLazily=true);
596596

597597
/// Look up the VTable mapped to the given ClassDecl. Returns null on failure.
598-
SILVTable *lookUpVTable(const ClassDecl *C);
598+
SILVTable *lookUpVTable(const ClassDecl *C, bool deserializeLazily = true);
599599

600600
/// Attempt to lookup the function corresponding to \p Member in the class
601601
/// hierarchy of \p Class.

include/swift/SIL/SILVTable.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,12 @@ class SILVTableEntry {
4949
/// The function which implements the method for the class and the entry kind.
5050
llvm::PointerIntPair<SILFunction *, 2, unsigned> ImplAndKind;
5151

52+
bool IsNonOverridden;
53+
5254
public:
5355
enum Kind : uint8_t {
5456
/// The vtable entry is for a method defined directly in this class.
5557
Normal,
56-
/// The vtable entry is for a method defined directly in this class, and is
57-
/// never overridden by subclasses.
58-
NormalNonOverridden,
5958
/// The vtable entry is inherited from the superclass.
6059
Inherited,
6160
/// The vtable entry is inherited from the superclass, and overridden
@@ -67,14 +66,19 @@ class SILVTableEntry {
6766

6867
SILVTableEntry() : ImplAndKind(nullptr, Kind::Normal) {}
6968

70-
SILVTableEntry(SILDeclRef Method, SILFunction *Implementation, Kind TheKind)
71-
: Method(Method), ImplAndKind(Implementation, TheKind) {}
69+
SILVTableEntry(SILDeclRef Method, SILFunction *Implementation, Kind TheKind,
70+
bool NonOverridden)
71+
: Method(Method), ImplAndKind(Implementation, TheKind),
72+
IsNonOverridden(NonOverridden) {}
7273

7374
SILDeclRef getMethod() const { return Method; }
7475

7576
Kind getKind() const { return Kind(ImplAndKind.getInt()); }
7677
void setKind(Kind kind) { ImplAndKind.setInt(kind); }
7778

79+
bool isNonOverridden() const { return IsNonOverridden; }
80+
void setNonOverridden(bool value) { IsNonOverridden = value; }
81+
7882
SILFunction *getImplementation() const { return ImplAndKind.getPointer(); }
7983
};
8084

lib/AST/Type.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -2208,6 +2208,16 @@ getObjCObjectRepresentable(Type type, const DeclContext *dc) {
22082208
static std::pair<ForeignRepresentableKind, ProtocolConformance *>
22092209
getForeignRepresentable(Type type, ForeignLanguage language,
22102210
const DeclContext *dc) {
2211+
// Local function that simply produces a failing result.
2212+
auto failure = []() -> std::pair<ForeignRepresentableKind,
2213+
ProtocolConformance *> {
2214+
return { ForeignRepresentableKind::None, nullptr };
2215+
};
2216+
2217+
// If type has an error let's fail early.
2218+
if (type->hasError())
2219+
return failure();
2220+
22112221
// Look through one level of optional type, but remember that we did.
22122222
bool wasOptional = false;
22132223
if (auto valueType = type->getOptionalObjectType()) {
@@ -2222,12 +2232,6 @@ getForeignRepresentable(Type type, ForeignLanguage language,
22222232
return { representable, nullptr };
22232233
}
22242234

2225-
// Local function that simply produces a failing result.
2226-
auto failure = []() -> std::pair<ForeignRepresentableKind,
2227-
ProtocolConformance *> {
2228-
return { ForeignRepresentableKind::None, nullptr };
2229-
};
2230-
22312235
// Function types.
22322236
if (auto functionType = type->getAs<FunctionType>()) {
22332237
// Cannot handle throwing functions.

lib/ClangImporter/ImportName.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14231423
case clang::OverloadedOperatorKind::OO_Minus:
14241424
case clang::OverloadedOperatorKind::OO_Star:
14251425
case clang::OverloadedOperatorKind::OO_Slash:
1426+
case clang::OverloadedOperatorKind::OO_Percent:
1427+
case clang::OverloadedOperatorKind::OO_Amp:
1428+
case clang::OverloadedOperatorKind::OO_Pipe:
14261429
case clang::OverloadedOperatorKind::OO_LessLess:
14271430
case clang::OverloadedOperatorKind::OO_GreaterGreater:
14281431
case clang::OverloadedOperatorKind::OO_AmpAmp:

lib/IRGen/ClassMetadataVisitor.h

+26-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "swift/AST/ASTContext.h"
2222
#include "swift/AST/SubstitutionMap.h"
2323
#include "swift/SIL/SILDeclRef.h"
24+
#include "swift/SIL/SILModule.h"
25+
#include "swift/SIL/SILVTable.h"
2426
#include "swift/SIL/SILVTableVisitor.h"
2527
#include "IRGen.h"
2628
#include "NominalMetadataVisitor.h"
@@ -30,6 +32,15 @@ namespace irgen {
3032

3133
class IRGenModule;
3234

35+
/// Returns true if the given SILVTable entry needs to be reified as a runtime
36+
/// vtable entry.
37+
///
38+
/// Methods that have no overrides, and no ABI constraints that require a
39+
/// vtable to be present, can be left out of the runtime vtable for classes.
40+
bool methodRequiresReifiedVTableEntry(IRGenModule &IGM,
41+
const SILVTable *vtable,
42+
SILDeclRef method);
43+
3344
/// A CRTP class for laying out class metadata. Note that this does
3445
/// *not* handle the metadata template stuff.
3546
template <class Impl> class ClassMetadataVisitor
@@ -43,9 +54,13 @@ template <class Impl> class ClassMetadataVisitor
4354

4455
/// The most-derived class.
4556
ClassDecl *const Target;
57+
58+
/// SILVTable entry for the class.
59+
const SILVTable *VTable;
4660

4761
ClassMetadataVisitor(IRGenModule &IGM, ClassDecl *target)
48-
: super(IGM), Target(target) {}
62+
: super(IGM), Target(target),
63+
VTable(IGM.getSILModule().lookUpVTable(target, /*deserialize*/ false)) {}
4964

5065
public:
5166
void layout() {
@@ -152,8 +167,15 @@ template <class Impl> class ClassMetadataVisitor
152167
// Add vtable entries.
153168
asImpl().addVTableEntries(theClass);
154169
}
155-
156-
private:
170+
171+
friend SILVTableVisitor<Impl>;
172+
void addMethod(SILDeclRef declRef) {
173+
// Does this method require a reified runtime vtable entry?
174+
if (methodRequiresReifiedVTableEntry(IGM, VTable, declRef)) {
175+
asImpl().addReifiedVTableEntry(declRef);
176+
}
177+
}
178+
157179
void addFieldEntries(Decl *field) {
158180
if (auto var = dyn_cast<VarDecl>(field)) {
159181
asImpl().addFieldOffset(var);
@@ -194,7 +216,7 @@ class ClassMetadataScanner : public ClassMetadataVisitor<Impl> {
194216
void addClassAddressPoint() { addInt32(); }
195217
void addClassCacheData() { addPointer(); addPointer(); }
196218
void addClassDataPointer() { addPointer(); }
197-
void addMethod(SILDeclRef declRef) {
219+
void addReifiedVTableEntry(SILDeclRef declRef) {
198220
addPointer();
199221
}
200222
void addMethodOverride(SILDeclRef baseRef, SILDeclRef declRef) {}

lib/IRGen/GenMeta.cpp

+61-9
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,13 @@ namespace {
14371437
}
14381438

14391439
void addMethod(SILDeclRef fn) {
1440-
VTableEntries.push_back(fn);
1440+
if (methodRequiresReifiedVTableEntry(IGM, VTable, fn)) {
1441+
VTableEntries.push_back(fn);
1442+
} else if (getType()->getEffectiveAccess() >= AccessLevel::Public) {
1443+
// Emit a stub method descriptor and lookup function for nonoverridden
1444+
// methods so that resilient code sequences can still use them.
1445+
emitNonoverriddenMethod(fn);
1446+
}
14411447
}
14421448

14431449
void addMethodOverride(SILDeclRef baseRef, SILDeclRef declRef) {
@@ -1521,9 +1527,6 @@ namespace {
15211527
}
15221528

15231529
void addVTable() {
1524-
if (VTableEntries.empty())
1525-
return;
1526-
15271530
LLVM_DEBUG(
15281531
llvm::dbgs() << "VTable entries for " << getType()->getName() << ":\n";
15291532
for (auto entry : VTableEntries) {
@@ -1533,6 +1536,9 @@ namespace {
15331536
}
15341537
);
15351538

1539+
if (VTableEntries.empty())
1540+
return;
1541+
15361542
// Only emit a method lookup function if the class is resilient
15371543
// and has a non-empty vtable.
15381544
if (IGM.hasResilientMetadata(getType(), ResilienceExpansion::Minimal))
@@ -1595,8 +1601,25 @@ namespace {
15951601
IGM.emitDispatchThunk(fn);
15961602
}
15971603
}
1604+
1605+
void emitNonoverriddenMethod(SILDeclRef fn) {
1606+
// TODO: Emit a freestanding method descriptor structure, and a method
1607+
// lookup function, to present the ABI of an overridable method even
1608+
// though the method has no real overrides currently.
1609+
}
15981610

15991611
void addOverrideTable() {
1612+
LLVM_DEBUG(
1613+
llvm::dbgs() << "Override Table entries for " << getType()->getName() << ":\n";
1614+
for (auto entry : OverrideTableEntries) {
1615+
llvm::dbgs() << " ";
1616+
entry.first.print(llvm::dbgs());
1617+
llvm::dbgs() << " -> ";
1618+
entry.second.print(llvm::dbgs());
1619+
llvm::dbgs() << '\n';
1620+
}
1621+
);
1622+
16001623
if (OverrideTableEntries.empty())
16011624
return;
16021625

@@ -2702,12 +2725,12 @@ namespace {
27022725
using super::asImpl;
27032726
using super::IGM;
27042727
using super::Target;
2728+
using super::VTable;
27052729

27062730
ConstantStructBuilder &B;
27072731

27082732
const ClassLayout &FieldLayout;
27092733
const ClassMetadataLayout &MetadataLayout;
2710-
const SILVTable *VTable;
27112734

27122735
Size AddressPoint;
27132736

@@ -2717,8 +2740,7 @@ namespace {
27172740
const ClassLayout &fieldLayout)
27182741
: super(IGM, theClass), B(builder),
27192742
FieldLayout(fieldLayout),
2720-
MetadataLayout(IGM.getClassMetadataLayout(theClass)),
2721-
VTable(IGM.getSILModule().lookUpVTable(theClass)) {}
2743+
MetadataLayout(IGM.getClassMetadataLayout(theClass)) {}
27222744

27232745
public:
27242746
SILType getLoweredType() {
@@ -2854,7 +2876,7 @@ namespace {
28542876
PointerAuthEntity::Special::HeapDestructor);
28552877
} else {
28562878
// In case the optimizer removed the function. See comment in
2857-
// addMethod().
2879+
// addReifiedVTableEntry().
28582880
B.addNullPointer(IGM.FunctionPtrTy);
28592881
}
28602882
}
@@ -2973,7 +2995,7 @@ namespace {
29732995
B.add(data);
29742996
}
29752997

2976-
void addMethod(SILDeclRef fn) {
2998+
void addReifiedVTableEntry(SILDeclRef fn) {
29772999
// Find the vtable entry.
29783000
assert(VTable && "no vtable?!");
29793001
auto entry = VTable->getEntry(IGM.getSILModule(), fn);
@@ -5086,3 +5108,33 @@ void IRGenModule::emitOpaqueTypeDecl(OpaqueTypeDecl *D) {
50865108
// Emit the opaque type descriptor.
50875109
OpaqueTypeDescriptorBuilder(*this, D).emit();
50885110
}
5111+
5112+
bool irgen::methodRequiresReifiedVTableEntry(IRGenModule &IGM,
5113+
const SILVTable *vtable,
5114+
SILDeclRef method) {
5115+
auto &M = IGM.getSILModule();
5116+
auto entry = vtable->getEntry(IGM.getSILModule(), method);
5117+
if (!entry) {
5118+
return true;
5119+
}
5120+
5121+
// We may be able to elide the vtable entry, ABI permitting, if it's not
5122+
// overridden.
5123+
if (!entry->isNonOverridden()) {
5124+
return true;
5125+
}
5126+
5127+
// Does the ABI require a vtable entry to exist? If the class is public,
5128+
// and it's either marked fragile or part of a non-resilient module, then
5129+
// other modules will directly address vtable offsets and we can't remove
5130+
// vtable entries.
5131+
if (vtable->getClass()->getEffectiveAccess() >= AccessLevel::Public) {
5132+
// TODO: Check whether we use a resilient ABI to access this
5133+
// class's methods. We can drop unnecessary vtable entries if we do;
5134+
// otherwise fixed vtable offsets are part of the ABI.
5135+
return true;
5136+
}
5137+
5138+
// Otherwise, we can leave this method out of the runtime vtable.
5139+
return false;
5140+
}

lib/IRGen/MetadataLayout.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -330,12 +330,12 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
330330
super::addGenericArgument(requirement, forClass);
331331
}
332332

333-
void addMethod(SILDeclRef fn) {
333+
void addReifiedVTableEntry(SILDeclRef fn) {
334334
if (fn.getDecl()->getDeclContext() == Target) {
335335
++Layout.NumImmediateMembers;
336336
Layout.MethodInfos.try_emplace(fn, getNextOffset());
337337
}
338-
super::addMethod(fn);
338+
super::addReifiedVTableEntry(fn);
339339
}
340340

341341
void noteStartOfFieldOffsets(ClassDecl *forClass) {

lib/SIL/IR/SILModule.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,8 @@ void SILModule::eraseGlobalVariable(SILGlobalVariable *G) {
476476
getSILGlobalList().erase(G);
477477
}
478478

479-
SILVTable *SILModule::lookUpVTable(const ClassDecl *C) {
479+
SILVTable *SILModule::lookUpVTable(const ClassDecl *C,
480+
bool deserializeLazily) {
480481
if (!C)
481482
return nullptr;
482483

@@ -485,6 +486,9 @@ SILVTable *SILModule::lookUpVTable(const ClassDecl *C) {
485486
if (R != VTableMap.end())
486487
return R->second;
487488

489+
if (!deserializeLazily)
490+
return nullptr;
491+
488492
// If that fails, try to deserialize it. If that fails, return nullptr.
489493
SILVTable *Vtbl = getSILLoader()->lookupVTable(C);
490494
if (!Vtbl)

lib/SIL/IR/SILPrinter.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -3131,16 +3131,17 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const {
31313131
switch (entry.getKind()) {
31323132
case SILVTable::Entry::Kind::Normal:
31333133
break;
3134-
case SILVTable::Entry::Kind::NormalNonOverridden:
3135-
OS << " [nonoverridden]";
3136-
break;
31373134
case SILVTable::Entry::Kind::Inherited:
31383135
OS << " [inherited]";
31393136
break;
31403137
case SILVTable::Entry::Kind::Override:
31413138
OS << " [override]";
31423139
break;
31433140
}
3141+
if (entry.isNonOverridden()) {
3142+
OS << " [nonoverridden]";
3143+
}
3144+
31443145
OS << "\t// " << demangleSymbol(entry.getImplementation()->getName());
31453146
OS << "\n";
31463147
}

0 commit comments

Comments
 (0)