29
29
#include " swift/SIL/SILModule.h"
30
30
#include " clang/AST/ASTContext.h"
31
31
#include " clang/AST/Attr.h"
32
+ #include " clang/AST/CharUnits.h"
32
33
#include " clang/AST/Decl.h"
34
+ #include " clang/AST/DeclCXX.h"
33
35
#include " clang/AST/GlobalDecl.h"
34
36
#include " clang/AST/Mangle.h"
35
37
#include " clang/AST/RecordLayout.h"
36
38
#include " clang/CodeGen/CodeGenABITypes.h"
37
39
#include " clang/CodeGen/SwiftCallingConv.h"
38
40
#include " clang/Sema/Sema.h"
41
+ #include " llvm/ADT/STLExtras.h"
39
42
#include " llvm/IR/DerivedTypes.h"
40
43
#include " llvm/IR/Function.h"
44
+ #include < iterator>
41
45
42
46
#include " GenDecl.h"
43
47
#include " GenMeta.h"
@@ -1310,6 +1314,7 @@ class ClangRecordLowering {
1310
1314
SmallVector<llvm::Type *, 8 > LLVMFields;
1311
1315
SmallVector<ClangFieldInfo, 8 > FieldInfos;
1312
1316
Size NextOffset = Size (0 );
1317
+ Size SubobjectAdjustment = Size (0 );
1313
1318
unsigned NextExplosionIndex = 0 ;
1314
1319
public:
1315
1320
ClangRecordLowering (IRGenModule &IGM, StructDecl *swiftDecl,
@@ -1327,8 +1332,8 @@ class ClangRecordLowering {
1327
1332
if (ClangDecl->isUnion ()) {
1328
1333
collectUnionFields ();
1329
1334
} else {
1330
- collectBases ();
1331
- collectStructFields ();
1335
+ collectBases (ClangDecl );
1336
+ collectStructFields (ClangDecl );
1332
1337
}
1333
1338
}
1334
1339
@@ -1359,10 +1364,9 @@ class ClangRecordLowering {
1359
1364
return (swiftField->getClangNode ().castAsDecl () == clangField);
1360
1365
}
1361
1366
1362
- void collectBases () {
1363
- auto &layout = ClangDecl->getASTContext ().getASTRecordLayout (ClangDecl);
1364
-
1365
- if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(ClangDecl)) {
1367
+ void collectBases (const clang::RecordDecl *decl) {
1368
+ auto &layout = decl->getASTContext ().getASTRecordLayout (decl);
1369
+ if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(decl)) {
1366
1370
for (auto base : cxxRecord->bases ()) {
1367
1371
if (base.isVirtual ())
1368
1372
continue ;
@@ -1375,17 +1379,24 @@ class ClangRecordLowering {
1375
1379
if (baseCxxRecord->isEmpty ())
1376
1380
continue ;
1377
1381
1378
- auto offset = layout.getBaseClassOffset (baseCxxRecord);
1379
- auto size = ClangDecl->getASTContext ().getTypeSizeInChars (baseType);
1380
- addOpaqueField (Size (offset.getQuantity ()), Size (size.getQuantity ()));
1382
+ auto baseOffset = Size (layout.getBaseClassOffset (baseCxxRecord).getQuantity ());
1383
+ SubobjectAdjustment += baseOffset;
1384
+ collectBases (baseCxxRecord);
1385
+ collectStructFields (baseCxxRecord);
1386
+ SubobjectAdjustment -= baseOffset;
1381
1387
}
1382
1388
}
1383
1389
}
1384
1390
1385
- void collectStructFields () {
1386
- auto cfi = ClangDecl->field_begin (), cfe = ClangDecl->field_end ();
1391
+ void collectStructFields (const clang::RecordDecl *decl) {
1392
+ auto cfi = decl->field_begin (), cfe = decl->field_end ();
1393
+ const auto & layout = ClangContext.getASTRecordLayout (decl);
1387
1394
auto swiftProperties = SwiftDecl->getStoredProperties ();
1388
1395
auto sfi = swiftProperties.begin (), sfe = swiftProperties.end ();
1396
+ // When collecting fields from the base subobjects, we do not have corresponding swift
1397
+ // stored properties.
1398
+ if (decl != ClangDecl)
1399
+ sfi = swiftProperties.end ();
1389
1400
1390
1401
while (cfi != cfe) {
1391
1402
const clang::FieldDecl *clangField = *cfi++;
@@ -1395,13 +1406,13 @@ class ClangRecordLowering {
1395
1406
if (clangField->isBitField ()) {
1396
1407
// Collect all of the following bitfields.
1397
1408
unsigned bitStart =
1398
- ClangLayout .getFieldOffset (clangField->getFieldIndex ());
1409
+ layout .getFieldOffset (clangField->getFieldIndex ());
1399
1410
unsigned bitEnd = bitStart + clangField->getBitWidthValue (ClangContext);
1400
1411
1401
1412
while (cfi != cfe && (*cfi)->isBitField ()) {
1402
1413
clangField = *cfi++;
1403
1414
unsigned nextStart =
1404
- ClangLayout .getFieldOffset (clangField->getFieldIndex ());
1415
+ layout .getFieldOffset (clangField->getFieldIndex ());
1405
1416
assert (nextStart >= bitEnd && " laying out bit-fields out of order?" );
1406
1417
1407
1418
// In a heuristic effort to reduce the number of weird-sized
@@ -1419,41 +1430,41 @@ class ClangRecordLowering {
1419
1430
continue ;
1420
1431
}
1421
1432
1422
- VarDecl *swiftField;
1433
+ VarDecl *swiftField = nullptr ;
1423
1434
if (sfi != sfe) {
1424
1435
swiftField = *sfi;
1425
1436
if (isImportOfClangField (swiftField, clangField)) {
1426
1437
++sfi;
1427
1438
} else {
1428
1439
swiftField = nullptr ;
1429
1440
}
1430
- } else {
1431
- swiftField = nullptr ;
1432
- }
1441
+ }
1433
1442
1434
1443
// Try to position this field. If this fails, it's because we
1435
1444
// didn't lay out padding correctly.
1436
- addStructField (clangField, swiftField);
1445
+ addStructField (clangField, swiftField, layout );
1437
1446
}
1438
1447
1439
1448
assert (sfi == sfe && " more Swift fields than there were Clang fields?" );
1440
1449
1450
+ Size objectTotalStride = Size (layout.getSize ().getQuantity ());
1441
1451
// We never take advantage of tail padding, because that would prevent
1442
1452
// us from passing the address of the object off to C, which is a pretty
1443
1453
// likely scenario for imported C types.
1444
- assert (NextOffset <= TotalStride);
1445
- assert (SpareBits.size () <= TotalStride.getValueInBits ());
1446
- if (NextOffset < TotalStride) {
1447
- addPaddingField (TotalStride);
1454
+ assert (NextOffset <= SubobjectAdjustment + objectTotalStride);
1455
+ assert (SpareBits.size () <= SubobjectAdjustment.getValueInBits () +
1456
+ objectTotalStride.getValueInBits ());
1457
+ if (NextOffset < objectTotalStride) {
1458
+ addPaddingField (objectTotalStride);
1448
1459
}
1449
1460
}
1450
1461
1451
1462
// / Place the next struct field at its appropriate offset.
1452
1463
void addStructField (const clang::FieldDecl *clangField,
1453
- VarDecl *swiftField) {
1454
- unsigned fieldOffset = ClangLayout .getFieldOffset (clangField->getFieldIndex ());
1464
+ VarDecl *swiftField, const clang::ASTRecordLayout& layout ) {
1465
+ unsigned fieldOffset = layout .getFieldOffset (clangField->getFieldIndex ());
1455
1466
assert (!clangField->isBitField ());
1456
- Size offset (fieldOffset / 8 );
1467
+ Size offset ( SubobjectAdjustment. getValue () + fieldOffset / 8 );
1457
1468
1458
1469
// If we have a Swift import of this type, use our lowered information.
1459
1470
if (swiftField) {
0 commit comments