25
25
using namespace swift ;
26
26
using namespace irgen ;
27
27
28
- static unsigned getNumLowObjCReservedBits (const IRGenModule &IGM) {
28
+ static uint8_t getNumLowObjCReservedBits (const IRGenModule &IGM) {
29
29
if (!IGM.ObjCInterop )
30
30
return 0 ;
31
31
@@ -34,16 +34,25 @@ static unsigned getNumLowObjCReservedBits(const IRGenModule &IGM) {
34
34
return mask.asAPInt ().countTrailingOnes ();
35
35
}
36
36
37
+ PointerInfo PointerInfo::forHeapObject (const IRGenModule &IGM) {
38
+ return { Alignment (1 ), getNumLowObjCReservedBits (IGM), IsNotNullable };
39
+ }
40
+
41
+ PointerInfo PointerInfo::forFunction (const IRGenModule &IGM) {
42
+ return { Alignment (1 ), 0 , IsNotNullable };
43
+ }
44
+
37
45
/* ****************************************************************************/
38
46
39
47
// / Return the number of extra inhabitants for a pointer that reserves
40
48
// / the given number of low bits.
41
- static unsigned getPointerExtraInhabitantCount (const IRGenModule &IGM,
42
- unsigned numReservedLowBits) {
49
+ unsigned PointerInfo::getExtraInhabitantCount (const IRGenModule &IGM) const {
43
50
// FIXME: We could also make extra inhabitants using spare bits, but we
44
51
// probably don't need to.
45
52
uint64_t rawCount =
46
- IGM.TargetInfo .LeastValidPointerValue >> numReservedLowBits;
53
+ IGM.TargetInfo .LeastValidPointerValue >> NumReservedLowBits;
54
+
55
+ if (Nullable) rawCount--;
47
56
48
57
// The runtime limits the count.
49
58
return std::min (uint64_t (ValueWitnessFlags::MaxNumExtraInhabitants),
@@ -54,35 +63,23 @@ unsigned irgen::getHeapObjectExtraInhabitantCount(const IRGenModule &IGM) {
54
63
// This must be consistent with the extra inhabitant count produced
55
64
// by the runtime's getHeapObjectExtraInhabitantCount function in
56
65
// KnownMetadata.cpp.
57
- return getPointerExtraInhabitantCount (IGM, getNumLowObjCReservedBits (IGM));
58
- }
59
-
60
- unsigned irgen::getFunctionPointerExtraInhabitantCount (IRGenModule &IGM) {
61
- return getPointerExtraInhabitantCount (IGM, 0 );
62
- }
63
-
64
- unsigned irgen::getAlignedPointerExtraInhabitantCount (IRGenModule &IGM,
65
- Alignment align) {
66
- // For all of the operations on current platforms, we totally ignore
67
- // alignment because we assume we can get what we consider to be an
68
- // adequate number of extra inhabitants from LeastValidPointerValue.
69
- // If we have to revisit that for a future ABI, we can take advantage
70
- // of alignment bits.
71
- return getPointerExtraInhabitantCount (IGM, 0 );
66
+ return PointerInfo::forHeapObject (IGM).getExtraInhabitantCount (IGM);
72
67
}
73
68
74
69
/* ****************************************************************************/
75
70
76
- static APInt
77
- getPointerFixedExtraInhabitantValue ( const IRGenModule &IGM, unsigned bits,
78
- unsigned index, unsigned offset ,
79
- unsigned numReservedLowBits) {
71
+ APInt PointerInfo::getFixedExtraInhabitantValue ( const IRGenModule &IGM,
72
+ unsigned bits,
73
+ unsigned index ,
74
+ unsigned offset) const {
80
75
unsigned pointerSizeInBits = IGM.getPointerSize ().getValueInBits ();
81
- assert (index < getPointerExtraInhabitantCount (IGM, numReservedLowBits ) &&
76
+ assert (index < getExtraInhabitantCount (IGM) &&
82
77
" pointer extra inhabitant out of bounds" );
83
78
assert (bits >= pointerSizeInBits + offset);
84
79
85
- uint64_t value = (uint64_t )index << numReservedLowBits;
80
+ if (Nullable) index++;
81
+
82
+ uint64_t value = (uint64_t )index << NumReservedLowBits;
86
83
87
84
auto valueBits = BitPatternBuilder (IGM.Triple .isLittleEndian ());
88
85
valueBits.appendClearBits (offset);
@@ -98,30 +95,14 @@ APInt irgen::getHeapObjectFixedExtraInhabitantValue(const IRGenModule &IGM,
98
95
// This must be consistent with the extra inhabitant calculation implemented
99
96
// in the runtime's storeHeapObjectExtraInhabitant and
100
97
// getHeapObjectExtraInhabitantIndex functions in KnownMetadata.cpp.
101
- return getPointerFixedExtraInhabitantValue (IGM, bits, index, offset,
102
- getNumLowObjCReservedBits (IGM));
103
- }
104
-
105
- APInt irgen::getFunctionPointerFixedExtraInhabitantValue (IRGenModule &IGM,
106
- unsigned bits,
107
- unsigned index,
108
- unsigned offset) {
109
- return getPointerFixedExtraInhabitantValue (IGM, bits, index, offset, 0 );
110
- }
111
-
112
- APInt irgen::getAlignedPointerExtraInhabitantValue (IRGenModule &IGM,
113
- Alignment align,
114
- unsigned bits,
115
- unsigned index,
116
- unsigned offset) {
117
- return getPointerFixedExtraInhabitantValue (IGM, bits, index, offset, 0 );
98
+ return PointerInfo::forHeapObject (IGM)
99
+ .getFixedExtraInhabitantValue (IGM, bits, index, offset);
118
100
}
119
101
120
102
/* ****************************************************************************/
121
103
122
- static llvm::Value *getPointerExtraInhabitantIndex (IRGenFunction &IGF,
123
- Address src,
124
- unsigned numReservedLowBits) {
104
+ llvm::Value *PointerInfo::getExtraInhabitantIndex (IRGenFunction &IGF,
105
+ Address src) const {
125
106
llvm::BasicBlock *contBB = IGF.createBasicBlock (" is-valid-pointer" );
126
107
SmallVector<std::pair<llvm::BasicBlock*, llvm::Value*>, 3 > phiValues;
127
108
auto invalidIndex = llvm::ConstantInt::getSigned (IGF.IGM .Int32Ty , -1 );
@@ -140,12 +121,22 @@ static llvm::Value *getPointerExtraInhabitantIndex(IRGenFunction &IGF,
140
121
IGF.Builder .CreateCondBr (isValid, contBB, invalidBB);
141
122
IGF.Builder .emitBlock (invalidBB);
142
123
}
143
-
124
+
125
+ // If null is not an extra inhabitant, check if the inhabitant is null.
126
+ if (Nullable) {
127
+ auto null = llvm::ConstantInt::get (IGF.IGM .SizeTy , 0 );
128
+ auto isNonNull = IGF.Builder .CreateICmpNE (val, null);
129
+ phiValues.push_back ({IGF.Builder .GetInsertBlock (), invalidIndex});
130
+ llvm::BasicBlock *nonnullBB = IGF.createBasicBlock (" is-nonnull-pointer" );
131
+ IGF.Builder .CreateCondBr (isNonNull, nonnullBB, contBB);
132
+ IGF.Builder .emitBlock (nonnullBB);
133
+ }
134
+
144
135
// Check if the inhabitant has any reserved low bits set.
145
136
// FIXME: This check is unneeded if the type is known to be pure Swift.
146
- if (numReservedLowBits ) {
137
+ if (NumReservedLowBits ) {
147
138
auto objcMask =
148
- llvm::ConstantInt::get (IGF.IGM .SizeTy , (1 << numReservedLowBits ) - 1 );
139
+ llvm::ConstantInt::get (IGF.IGM .SizeTy , (1 << NumReservedLowBits ) - 1 );
149
140
llvm::Value *masked = IGF.Builder .CreateAnd (val, objcMask);
150
141
llvm::Value *maskedZero = IGF.Builder .CreateICmpEQ (masked,
151
142
llvm::ConstantInt::get (IGF.IGM .SizeTy , 0 ));
@@ -155,15 +146,20 @@ static llvm::Value *getPointerExtraInhabitantIndex(IRGenFunction &IGF,
155
146
IGF.Builder .CreateCondBr (maskedZero, untaggedBB, contBB);
156
147
IGF.Builder .emitBlock (untaggedBB);
157
148
}
158
-
149
+
159
150
// The inhabitant is an invalid pointer. Derive its extra inhabitant index.
160
151
{
161
152
llvm::Value *index = val;
162
153
163
154
// Shift away the reserved bits.
164
- if (numReservedLowBits) {
165
- index = IGF.Builder .CreateLShr (index,
166
- llvm::ConstantInt::get (IGF.IGM .SizeTy , numReservedLowBits));
155
+ if (NumReservedLowBits) {
156
+ index = IGF.Builder .CreateLShr (index,
157
+ IGF.IGM .getSize (Size (NumReservedLowBits)));
158
+ }
159
+
160
+ // Subtract one if we have a nullable type.
161
+ if (Nullable) {
162
+ index = IGF.Builder .CreateSub (index, IGF.IGM .getSize (Size (1 )));
167
163
}
168
164
169
165
// Truncate down to i32 if necessary.
@@ -189,34 +185,25 @@ llvm::Value *irgen::getHeapObjectExtraInhabitantIndex(IRGenFunction &IGF,
189
185
// This must be consistent with the extra inhabitant calculation implemented
190
186
// in the runtime's getHeapObjectExtraInhabitantIndex function in
191
187
// KnownMetadata.cpp.
192
- return getPointerExtraInhabitantIndex (IGF, src,
193
- getNumLowObjCReservedBits (IGF.IGM ));
194
- }
195
-
196
- llvm::Value *irgen::getFunctionPointerExtraInhabitantIndex (IRGenFunction &IGF,
197
- Address src) {
198
- return getPointerExtraInhabitantIndex (IGF, src, 0 );
199
- }
200
-
201
- llvm::Value *irgen::getAlignedPointerExtraInhabitantIndex (IRGenFunction &IGF,
202
- Alignment align,
203
- Address src) {
204
- return getPointerExtraInhabitantIndex (IGF, src, 0 );
188
+ return PointerInfo::forHeapObject (IGF.IGM ).getExtraInhabitantIndex (IGF, src);
205
189
}
206
190
207
191
/* ****************************************************************************/
208
192
209
- static void storePointerExtraInhabitant (IRGenFunction &IGF,
210
- llvm::Value *index,
211
- Address dest,
212
- unsigned numReservedLowBits) {
193
+ void PointerInfo::storeExtraInhabitant (IRGenFunction &IGF,
194
+ llvm::Value *index,
195
+ Address dest) const {
213
196
if (index->getType () != IGF.IGM .SizeTy ) {
214
197
index = IGF.Builder .CreateZExt (index, IGF.IGM .SizeTy );
215
198
}
216
199
217
- if (numReservedLowBits) {
200
+ if (Nullable) {
201
+ index = IGF.Builder .CreateAdd (index, IGF.IGM .getSize (Size (1 )));
202
+ }
203
+
204
+ if (NumReservedLowBits) {
218
205
index = IGF.Builder .CreateShl (index,
219
- llvm::ConstantInt::get (IGF.IGM .SizeTy , numReservedLowBits ));
206
+ llvm::ConstantInt::get (IGF.IGM .SizeTy , NumReservedLowBits ));
220
207
}
221
208
222
209
dest = IGF.Builder .CreateBitCast (dest, IGF.IGM .SizeTy ->getPointerTo ());
@@ -229,19 +216,6 @@ void irgen::storeHeapObjectExtraInhabitant(IRGenFunction &IGF,
229
216
// This must be consistent with the extra inhabitant calculation implemented
230
217
// in the runtime's storeHeapObjectExtraInhabitant function in
231
218
// KnownMetadata.cpp.
232
- storePointerExtraInhabitant (IGF, index, dest,
233
- getNumLowObjCReservedBits (IGF.IGM ));
234
- }
235
-
236
- void irgen::storeFunctionPointerExtraInhabitant (IRGenFunction &IGF,
237
- llvm::Value *index,
238
- Address dest) {
239
- storePointerExtraInhabitant (IGF, index, dest, 0 );
240
- }
241
-
242
- void irgen::storeAlignedPointerExtraInhabitant (IRGenFunction &IGF,
243
- Alignment align,
244
- llvm::Value *index,
245
- Address dest) {
246
- storePointerExtraInhabitant (IGF, index, dest, 0 );
219
+ PointerInfo::forHeapObject (IGF.IGM )
220
+ .storeExtraInhabitant (IGF, index, dest);
247
221
}
0 commit comments