@@ -2293,9 +2293,10 @@ getAddrOfDestructorFunction(IRGenModule &IGM, ClassDecl *classDecl) {
2293
2293
2294
2294
static void emitFieldOffsetGlobals (IRGenModule &IGM,
2295
2295
ClassDecl *classDecl,
2296
- const ClassLayout &classLayout) {
2296
+ const ClassLayout &fragileLayout,
2297
+ const ClassLayout &resilientLayout) {
2297
2298
for (auto prop : classDecl->getStoredProperties ()) {
2298
- auto fieldInfo = classLayout .getFieldAccessAndElement (prop);
2299
+ auto fieldInfo = fragileLayout .getFieldAccessAndElement (prop);
2299
2300
auto access = fieldInfo.first ;
2300
2301
auto element = fieldInfo.second ;
2301
2302
@@ -2323,8 +2324,19 @@ static void emitFieldOffsetGlobals(IRGenModule &IGM,
2323
2324
auto offsetVar = cast<llvm::GlobalVariable>(offsetAddr.getAddress ());
2324
2325
offsetVar->setInitializer (fieldOffsetOrZero);
2325
2326
2326
- // If we know the offset won't change, make it a constant.
2327
- offsetVar->setConstant (access == FieldAccess::ConstantDirect);
2327
+ // If the offset is constant in the resilient layout, it will not change
2328
+ // at runtime, and the global can be true const.
2329
+ //
2330
+ // If it is constant in the fragile layout only, newer Objective-C
2331
+ // runtimes will still update them in place, so make sure to check the
2332
+ // correct layout.
2333
+ auto resilientInfo = resilientLayout.getFieldAccessAndElement (prop);
2334
+ if (resilientInfo.first == FieldAccess::ConstantDirect) {
2335
+ // If it is constant in the resilient layout, it should be constant in
2336
+ // the fragile layout also.
2337
+ assert (access == FieldAccess::ConstantDirect);
2338
+ offsetVar->setConstant (true );
2339
+ }
2328
2340
2329
2341
break ;
2330
2342
}
@@ -3015,11 +3027,12 @@ static void emitObjCClassSymbol(IRGenModule &IGM,
3015
3027
3016
3028
// / Emit the type metadata or metadata template for a class.
3017
3029
void irgen::emitClassMetadata (IRGenModule &IGM, ClassDecl *classDecl,
3018
- const ClassLayout &fieldLayout) {
3030
+ const ClassLayout &fragileLayout,
3031
+ const ClassLayout &resilientLayout) {
3019
3032
assert (!classDecl->isForeign ());
3020
3033
PrettyStackTraceDecl stackTraceRAII (" emitting metadata for" , classDecl);
3021
3034
3022
- emitFieldOffsetGlobals (IGM, classDecl, fieldLayout );
3035
+ emitFieldOffsetGlobals (IGM, classDecl, fragileLayout, resilientLayout );
3023
3036
3024
3037
// Set up a dummy global to stand in for the metadata object while we produce
3025
3038
// relative references.
@@ -3034,28 +3047,28 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
3034
3047
bool canBeConstant;
3035
3048
if (classDecl->isGenericContext ()) {
3036
3049
GenericClassMetadataBuilder builder (IGM, classDecl, init,
3037
- fieldLayout );
3050
+ fragileLayout );
3038
3051
builder.layout ();
3039
3052
canBeConstant = true ;
3040
3053
3041
3054
builder.createMetadataAccessFunction ();
3042
3055
} else if (doesClassMetadataRequireRelocation (IGM, classDecl)) {
3043
3056
ResilientClassMetadataBuilder builder (IGM, classDecl, init,
3044
- fieldLayout );
3057
+ fragileLayout );
3045
3058
builder.layout ();
3046
3059
canBeConstant = true ;
3047
3060
3048
3061
builder.createMetadataAccessFunction ();
3049
3062
} else if (doesClassMetadataRequireInitialization (IGM, classDecl)) {
3050
3063
SingletonClassMetadataBuilder builder (IGM, classDecl, init,
3051
- fieldLayout );
3064
+ fragileLayout );
3052
3065
builder.layout ();
3053
3066
canBeConstant = builder.canBeConstant ();
3054
3067
3055
3068
builder.createMetadataAccessFunction ();
3056
3069
} else {
3057
3070
FixedClassMetadataBuilder builder (IGM, classDecl, init,
3058
- fieldLayout );
3071
+ fragileLayout );
3059
3072
builder.layout ();
3060
3073
canBeConstant = builder.canBeConstant ();
3061
3074
0 commit comments