29
29
#include " clang/CodeGen/SwiftCallingConv.h"
30
30
31
31
#include " EnumPayload.h"
32
+ #include " LegacyLayoutFormat.h"
32
33
#include " LoadableTypeInfo.h"
33
34
#include " GenMeta.h"
34
35
#include " GenProto.h"
@@ -56,16 +57,10 @@ Alignment IRGenModule::getCappedAlignment(Alignment align) {
56
57
}
57
58
58
59
llvm::DenseMap<TypeBase *, const TypeInfo *> &
59
- TypeConverter::Types_t::getCacheFor (bool isDependent, bool completelyFragile) {
60
- if (completelyFragile) {
61
- return (isDependent
62
- ? FragileDependentCache
63
- : FragileIndependentCache);
64
- }
65
-
60
+ TypeConverter::Types_t::getCacheFor (bool isDependent, TypeConverter::Mode mode) {
66
61
return (isDependent
67
- ? DependentCache
68
- : IndependentCache);
62
+ ? DependentCache[ unsigned (mode)]
63
+ : IndependentCache[ unsigned (mode)] );
69
64
}
70
65
71
66
void TypeInfo::assign (IRGenFunction &IGF, Address dest, Address src,
@@ -1071,6 +1066,54 @@ TypeConverter::createImmovable(llvm::Type *type, Size size, Alignment align) {
1071
1066
1072
1067
static TypeInfo *invalidTypeInfo () { return (TypeInfo*) 1 ; }
1073
1068
1069
+ bool TypeConverter::readLegacyTypeInfo (StringRef path) {
1070
+ auto fileOrErr = llvm::MemoryBuffer::getFile (path);
1071
+ if (!fileOrErr)
1072
+ return true ;
1073
+
1074
+ auto file = std::move (fileOrErr.get ());
1075
+
1076
+ llvm::yaml::Input yin (file->getBuffer ());
1077
+
1078
+ // Read the document list.
1079
+ std::vector<YAMLModuleNode> modules;
1080
+ yin >> modules;
1081
+
1082
+ if (yin.error ())
1083
+ return true ;
1084
+
1085
+ for (auto &module : modules) {
1086
+ for (auto &decl : module .Decls ) {
1087
+ auto result = LegacyTypeInfos.insert (std::make_pair (
1088
+ decl.Name ,
1089
+ decl));
1090
+ assert (result.second );
1091
+ (void ) result;
1092
+ }
1093
+ }
1094
+
1095
+ return false ;
1096
+ }
1097
+
1098
+ static std::string mangleTypeAsContext (const NominalTypeDecl *decl) {
1099
+ Mangle::ASTMangler Mangler;
1100
+ return Mangler.mangleTypeAsContextUSR (decl);
1101
+ }
1102
+
1103
+ Optional<YAMLTypeInfoNode>
1104
+ TypeConverter::getLegacyTypeInfo (NominalTypeDecl *decl) const {
1105
+ auto &mangledName = const_cast <TypeConverter *>(this )->DeclMangledNames [decl];
1106
+ if (mangledName.empty ())
1107
+ mangledName = mangleTypeAsContext (decl);
1108
+ assert (!mangledName.empty ());
1109
+
1110
+ auto found = LegacyTypeInfos.find (mangledName);
1111
+ if (found == LegacyTypeInfos.end ())
1112
+ return None;
1113
+
1114
+ return found->second ;
1115
+ }
1116
+
1074
1117
TypeConverter::TypeConverter (IRGenModule &IGM)
1075
1118
: IGM(IGM),
1076
1119
FirstType(invalidTypeInfo()) {
@@ -1080,7 +1123,15 @@ TypeConverter::TypeConverter(IRGenModule &IGM)
1080
1123
// sync with the binary module. Once LLDB can calculate type layouts at
1081
1124
// runtime (using remote mirrors or some other mechanism), we can remove this.
1082
1125
if (IGM.IRGen .Opts .EnableResilienceBypass )
1083
- CompletelyFragile = true ;
1126
+ LoweringMode = Mode::CompletelyFragile;
1127
+
1128
+ StringRef path = IGM.IRGen .Opts .ReadTypeInfoPath ;
1129
+ if (!path.empty ()) {
1130
+ bool error = readLegacyTypeInfo (path);
1131
+ if (error) {
1132
+ llvm::report_fatal_error (" Cannot read '" + path + " '" );
1133
+ }
1134
+ }
1084
1135
}
1085
1136
1086
1137
TypeConverter::~TypeConverter () {
@@ -1102,8 +1153,9 @@ void TypeConverter::pushGenericContext(CanGenericSignature signature) {
1102
1153
1103
1154
// Clear the dependent type info cache since we have a new active signature
1104
1155
// now.
1105
- Types.getCacheFor (/* isDependent*/ true , /* isFragile*/ false ).clear ();
1106
- Types.getCacheFor (/* isDependent*/ true , /* isFragile*/ true ).clear ();
1156
+ Types.getCacheFor (/* isDependent*/ true , Mode::Normal).clear ();
1157
+ Types.getCacheFor (/* isDependent*/ true , Mode::Legacy).clear ();
1158
+ Types.getCacheFor (/* isDependent*/ true , Mode::CompletelyFragile).clear ();
1107
1159
}
1108
1160
1109
1161
void TypeConverter::popGenericContext (CanGenericSignature signature) {
@@ -1113,8 +1165,9 @@ void TypeConverter::popGenericContext(CanGenericSignature signature) {
1113
1165
// Pop the SIL TypeConverter's generic context too.
1114
1166
IGM.getSILTypes ().popGenericContext (signature);
1115
1167
1116
- Types.getCacheFor (/* isDependent*/ true , /* isFragile*/ false ).clear ();
1117
- Types.getCacheFor (/* isDependent*/ true , /* isFragile*/ true ).clear ();
1168
+ Types.getCacheFor (/* isDependent*/ true , Mode::Normal).clear ();
1169
+ Types.getCacheFor (/* isDependent*/ true , Mode::Legacy).clear ();
1170
+ Types.getCacheFor (/* isDependent*/ true , Mode::CompletelyFragile).clear ();
1118
1171
}
1119
1172
1120
1173
GenericEnvironment *TypeConverter::getGenericEnvironment () {
@@ -1131,7 +1184,7 @@ GenericEnvironment *IRGenModule::getGenericEnvironment() {
1131
1184
void TypeConverter::addForwardDecl (TypeBase *key) {
1132
1185
assert (key->isCanonical ());
1133
1186
assert (!key->hasTypeParameter ());
1134
- auto &Cache = Types.getCacheFor (/* isDependent*/ false , CompletelyFragile );
1187
+ auto &Cache = Types.getCacheFor (/* isDependent*/ false , LoweringMode );
1135
1188
auto result = Cache.insert (std::make_pair (key, nullptr ));
1136
1189
assert (result.second && " entry already exists for type!" );
1137
1190
(void ) result;
@@ -1409,20 +1462,10 @@ CanType TypeConverter::getExemplarType(CanType contextTy) {
1409
1462
}
1410
1463
}
1411
1464
1412
- void TypeConverter::pushCompletelyFragile () {
1413
- assert (!CompletelyFragile);
1414
- CompletelyFragile = true ;
1415
- }
1416
-
1417
- void TypeConverter::popCompletelyFragile () {
1418
- assert (CompletelyFragile);
1419
- CompletelyFragile = false ;
1420
- }
1421
-
1422
1465
const TypeInfo *TypeConverter::getTypeEntry (CanType canonicalTy) {
1423
1466
// Cache this entry in the dependent or independent cache appropriate to it.
1424
1467
auto &Cache = Types.getCacheFor (canonicalTy->hasTypeParameter (),
1425
- CompletelyFragile );
1468
+ LoweringMode );
1426
1469
1427
1470
{
1428
1471
auto it = Cache.find (canonicalTy.getPointer ());
@@ -1447,7 +1490,7 @@ const TypeInfo *TypeConverter::getTypeEntry(CanType canonicalTy) {
1447
1490
1448
1491
// See whether we lowered a type equivalent to this one.
1449
1492
if (exemplarTy != canonicalTy) {
1450
- auto &Cache = Types.getCacheFor (/* isDependent*/ false , CompletelyFragile );
1493
+ auto &Cache = Types.getCacheFor (/* isDependent*/ false , LoweringMode );
1451
1494
auto it = Cache.find (exemplarTy.getPointer ());
1452
1495
if (it != Cache.end ()) {
1453
1496
// Record the object under the original type.
@@ -1469,7 +1512,7 @@ const TypeInfo *TypeConverter::getTypeEntry(CanType canonicalTy) {
1469
1512
insertEntry (Cache[canonicalTy.getPointer ()]);
1470
1513
if (canonicalTy != exemplarTy) {
1471
1514
auto &IndependentCache = Types.getCacheFor (/* isDependent*/ false ,
1472
- CompletelyFragile );
1515
+ LoweringMode );
1473
1516
insertEntry (IndependentCache[exemplarTy.getPointer ()]);
1474
1517
}
1475
1518
@@ -1809,11 +1852,94 @@ static bool isIRTypeDependent(IRGenModule &IGM, NominalTypeDecl *decl) {
1809
1852
}
1810
1853
}
1811
1854
1855
+ namespace {
1856
+
1857
+ class LegacyTypeInfo : public FixedTypeInfo {
1858
+ unsigned NumExtraInhabitants;
1859
+
1860
+ public:
1861
+ LegacyTypeInfo (llvm::Type *type, const SpareBitVector &spareBits,
1862
+ const YAMLTypeInfoNode &node)
1863
+ : FixedTypeInfo(type,
1864
+ Size (node.Size),
1865
+ spareBits,
1866
+ Alignment(node.Alignment),
1867
+ IsNotPOD, /* irrelevant */
1868
+ IsNotBitwiseTakable, /* irrelevant */
1869
+ IsFixedSize /* irrelevant */ ),
1870
+ NumExtraInhabitants(node.NumExtraInhabitants) {}
1871
+
1872
+ virtual unsigned getFixedExtraInhabitantCount (IRGenModule &IGM) const override {
1873
+ return NumExtraInhabitants;
1874
+ }
1875
+
1876
+ virtual APInt getFixedExtraInhabitantMask (IRGenModule &IGM) const override {
1877
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1878
+ }
1879
+
1880
+ virtual APInt getFixedExtraInhabitantValue (IRGenModule &IGM,
1881
+ unsigned bits,
1882
+ unsigned index) const override {
1883
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1884
+ }
1885
+
1886
+ virtual void getSchema (ExplosionSchema &schema) const override {
1887
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1888
+ }
1889
+
1890
+ virtual void assignWithCopy (IRGenFunction &IGF, Address dest, Address src,
1891
+ SILType T, bool isOutlined) const override {
1892
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1893
+ }
1894
+
1895
+ virtual void assignWithTake (IRGenFunction &IGF, Address dest, Address src,
1896
+ SILType T, bool isOutlined) const override {
1897
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1898
+ }
1899
+
1900
+ virtual void initializeWithCopy (IRGenFunction &IGF, Address destAddr,
1901
+ Address srcAddr, SILType T,
1902
+ bool isOutlined) const override {
1903
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1904
+ }
1905
+
1906
+ virtual void initializeFromParams (IRGenFunction &IGF, Explosion ¶ms,
1907
+ Address src, SILType T,
1908
+ bool isOutlined) const override {
1909
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1910
+ }
1911
+
1912
+ virtual void destroy (IRGenFunction &IGF, Address address, SILType T,
1913
+ bool isOutlined) const override {
1914
+ llvm_unreachable (" TypeConverter::Mode::Legacy is not for real values" );
1915
+ }
1916
+ };
1917
+
1918
+ } // namespace
1919
+
1812
1920
const TypeInfo *TypeConverter::convertAnyNominalType (CanType type,
1813
1921
NominalTypeDecl *decl) {
1814
1922
// By "any", we don't mean existentials.
1815
1923
assert (!isa<ProtocolDecl>(decl));
1816
1924
1925
+ // If we're producing a legacy type layout, and we have a serialized
1926
+ // record for this type, produce it now.
1927
+ if (LoweringMode == Mode::Legacy) {
1928
+ auto node = getLegacyTypeInfo (decl);
1929
+
1930
+ if (node) {
1931
+ Size size (node->Size );
1932
+
1933
+ auto ty = IGM.createNominalType (type);
1934
+ ty->setBody (llvm::ArrayType::get (IGM.Int8Ty , size.getValue ()));
1935
+
1936
+ SpareBitVector spareBits;
1937
+ spareBits.appendClearBits (size.getValueInBits ());
1938
+
1939
+ return new LegacyTypeInfo (ty, spareBits, *node);
1940
+ }
1941
+ }
1942
+
1817
1943
// We need to give generic specializations distinct TypeInfo objects
1818
1944
// if their IR-gen might be different, e.g. if they use different IR
1819
1945
// types or if type-specific operations like projections might need
@@ -1849,7 +1975,7 @@ const TypeInfo *TypeConverter::convertAnyNominalType(CanType type,
1849
1975
assert (decl->getDeclaredType ()->isCanonical ());
1850
1976
assert (decl->getDeclaredType ()->hasUnboundGenericType ());
1851
1977
TypeBase *key = decl->getDeclaredType ().getPointer ();
1852
- auto &Cache = Types.getCacheFor (/* isDependent*/ false , CompletelyFragile );
1978
+ auto &Cache = Types.getCacheFor (/* isDependent*/ false , LoweringMode );
1853
1979
auto entry = Cache.find (key);
1854
1980
if (entry != Cache.end ())
1855
1981
return entry->second ;
0 commit comments