Skip to content

Commit 1cfada4

Browse files
authored
Merge pull request #11675 from eeckstein/fix-static-init-4.0
IRGen: fix statically initialized globals which contain an empty type.
2 parents 67c31bc + 3f5d82e commit 1cfada4

File tree

7 files changed

+82
-19
lines changed

7 files changed

+82
-19
lines changed

lib/IRGen/GenConstant.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,13 @@ llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst,
9797
// appropriate.
9898
for (unsigned i = 0, e = inst->getElements().size(); i != e; i++) {
9999
auto operand = inst->getOperand(i);
100-
unsigned index = nextIndex(IGM, type, i);
100+
Optional<unsigned> index = nextIndex(IGM, type, i);
101+
if (index.hasValue()) {
102+
assert(elts[index.getValue()] == nullptr &&
103+
"Unexpected constant struct field overlap");
101104

102-
assert(elts[index] == nullptr &&
103-
"Unexpected constant struct field overlap");
104-
105-
elts[index] = emitConstantValue(IGM, operand);
105+
elts[index.getValue()] = emitConstantValue(IGM, operand);
106+
}
106107
}
107108

108109
// fill in any gaps, which are the explicit padding that swiftc inserts.
@@ -138,5 +139,6 @@ llvm::Constant *irgen::emitConstantStruct(IRGenModule &IGM, StructInst *SI) {
138139
}
139140

140141
llvm::Constant *irgen::emitConstantTuple(IRGenModule &IGM, TupleInst *TI) {
141-
return emitConstantStructOrTuple(IGM, TI, irgen::getTupleElementStructIndex);
142+
return emitConstantStructOrTuple(IGM, TI,
143+
irgen::getPhysicalTupleElementStructIndex);
142144
}

lib/IRGen/GenKeyPath.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,9 +535,10 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
535535
idKind = KeyPathComponentHeader::StoredPropertyIndex;
536536
if (baseTy->getStructOrBoundGenericStruct()) {
537537
idResolved = true;
538-
idValue = llvm::ConstantInt::get(SizeTy,
539-
getPhysicalStructFieldIndex(*this,
540-
SILType::getPrimitiveAddressType(baseTy), property));
538+
Optional<unsigned> structIdx = getPhysicalStructFieldIndex(*this,
539+
SILType::getPrimitiveAddressType(baseTy), property);
540+
assert(structIdx.hasValue() && "empty property");
541+
idValue = llvm::ConstantInt::get(SizeTy, structIdx.getValue());
541542
} else if (baseTy->getClassOrBoundGenericClass()) {
542543
// TODO: This field index would require runtime resolution with Swift
543544
// native class resilience. We never directly access ObjC-imported

lib/IRGen/GenStruct.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,14 @@ namespace {
191191
return fieldInfo.getStructIndex();
192192
}
193193

194+
Optional<unsigned> getFieldIndexIfNotEmpty(IRGenModule &IGM,
195+
VarDecl *field) const {
196+
auto &fieldInfo = getFieldInfo(field);
197+
if (fieldInfo.isEmpty())
198+
return None;
199+
return fieldInfo.getStructIndex();
200+
}
201+
194202
// For now, just use extra inhabitants from the first field.
195203
// FIXME: generalize
196204
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
@@ -867,9 +875,10 @@ irgen::getPhysicalStructMemberAccessStrategy(IRGenModule &IGM,
867875
FOR_STRUCT_IMPL(IGM, baseType, getFieldAccessStrategy, baseType, field);
868876
}
869877

870-
unsigned irgen::getPhysicalStructFieldIndex(IRGenModule &IGM, SILType baseType,
871-
VarDecl *field) {
872-
FOR_STRUCT_IMPL(IGM, baseType, getFieldIndex, field);
878+
Optional<unsigned> irgen::getPhysicalStructFieldIndex(IRGenModule &IGM,
879+
SILType baseType,
880+
VarDecl *field) {
881+
FOR_STRUCT_IMPL(IGM, baseType, getFieldIndexIfNotEmpty, field);
873882
}
874883

875884
void IRGenModule::emitStructDecl(StructDecl *st) {

lib/IRGen/GenStruct.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#ifndef SWIFT_IRGEN_GENSTRUCT_H
1818
#define SWIFT_IRGEN_GENSTRUCT_H
1919

20+
#include "llvm/ADT/Optional.h"
21+
2022
namespace llvm {
2123
class Constant;
2224
}
@@ -63,8 +65,14 @@ namespace irgen {
6365
getPhysicalStructMemberAccessStrategy(IRGenModule &IGM,
6466
SILType baseType, VarDecl *field);
6567

66-
unsigned getPhysicalStructFieldIndex(IRGenModule &IGM, SILType baseType,
67-
VarDecl *field);
68+
/// Returns the index of the element in the llvm struct type which represents
69+
/// \p field in \p baseType.
70+
///
71+
/// Returns None if \p field has an empty type and therefore has no
72+
/// corresponding element in the llvm type.
73+
llvm::Optional<unsigned> getPhysicalStructFieldIndex(IRGenModule &IGM,
74+
SILType baseType,
75+
VarDecl *field);
6876

6977
} // end namespace irgen
7078
} // end namespace swift

lib/IRGen/GenTuple.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,11 @@ namespace {
129129
llvm_unreachable("bad element layout kind");
130130
}
131131

132-
unsigned getElementStructIndex(IRGenModule &IGM, unsigned fieldNo) const {
132+
Optional<unsigned> getElementStructIndex(IRGenModule &IGM,
133+
unsigned fieldNo) const {
133134
const TupleFieldInfo &field = asImpl().getFields()[fieldNo];
135+
if (field.isEmpty())
136+
return None;
134137
return field.getStructIndex();
135138
}
136139

@@ -412,7 +415,8 @@ Optional<Size> irgen::getFixedTupleElementOffset(IRGenModule &IGM,
412415
FOR_TUPLE_IMPL(IGM, tupleType, getFixedElementOffset, fieldNo);
413416
}
414417

415-
unsigned irgen::getTupleElementStructIndex(IRGenModule &IGM, SILType tupleType,
416-
unsigned fieldNo) {
418+
Optional<unsigned> irgen::getPhysicalTupleElementStructIndex(IRGenModule &IGM,
419+
SILType tupleType,
420+
unsigned fieldNo) {
417421
FOR_TUPLE_IMPL(IGM, tupleType, getElementStructIndex, fieldNo);
418422
}

lib/IRGen/GenTuple.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ namespace irgen {
4848
SILType tupleType,
4949
unsigned fieldNo);
5050

51-
unsigned getTupleElementStructIndex(IRGenModule &IGM, SILType tupleType,
52-
unsigned fieldNo);
51+
/// Returns the index of the element in the llvm struct type which represents
52+
/// \p fieldNo in \p tupleType.
53+
///
54+
/// Returns None if the tuple element is an empty type and therefore has no
55+
/// corresponding element in the llvm type.
56+
Optional<unsigned> getPhysicalTupleElementStructIndex(IRGenModule &IGM,
57+
SILType tupleType,
58+
unsigned fieldNo);
5359
} // end namespace irgen
5460
} // end namespace swift
5561

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-swift-frontend -primary-file %s -O -module-name=test -emit-ir | %FileCheck %s
2+
3+
// Also do an end-to-end test.
4+
// RUN: %empty-directory(%t)
5+
// RUN: %target-build-swift -O -module-name=test %s -o %t/a.out
6+
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
7+
// REQUIRES: executable_test,optimized_stdlib
8+
9+
struct Empty { }
10+
11+
struct Mystruct {
12+
var a: Int
13+
var b: Empty
14+
var c: Int
15+
16+
// CHECK: @{{[^ ]*structglobal[^ ]*}} = hidden global %{{[^ ]*}} <{ %TSi <{ i{{[0-9]+}} 3 }>, %TSi <{ i{{[0-9]+}} 4 }> }>
17+
static var structglobal = Mystruct(a: 3, b: Empty(), c: 4)
18+
// CHECK: @{{[^ ]*tupleglobal[^ ]*}} = hidden global <{ %TSi, %TSi }> <{ %TSi <{ i{{[0-9]+}} 5 }>, %TSi <{ i{{[0-9]+}} 6 }> }>
19+
static var tupleglobal = (a: 5, b: Empty(), c: 6)
20+
}
21+
22+
// CHECK-OUTPUT: 3
23+
print(Mystruct.structglobal.a)
24+
// CHECK-OUTPUT-NEXT: Empty()
25+
print(Mystruct.structglobal.b)
26+
// CHECK-OUTPUT-NEXT: 4
27+
print(Mystruct.structglobal.c)
28+
// CHECK-OUTPUT-NEXT: 5
29+
print(Mystruct.tupleglobal.a)
30+
// CHECK-OUTPUT-NEXT: Empty()
31+
print(Mystruct.tupleglobal.b)
32+
// CHECK-OUTPUT-NEXT: 6
33+
print(Mystruct.tupleglobal.c)

0 commit comments

Comments
 (0)