Skip to content

Commit 2e8d016

Browse files
committed
Make an IRGen abstraction for pointer type properties.
NFC except that I've also added support for nullable pointers, where 0 is a valid value (not an extra inhabitant). I'll use this for executors.
1 parent 57c0c78 commit 2e8d016

File tree

4 files changed

+145
-169
lines changed

4 files changed

+145
-169
lines changed

lib/IRGen/ExtraInhabitants.cpp

Lines changed: 60 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
using namespace swift;
2626
using namespace irgen;
2727

28-
static unsigned getNumLowObjCReservedBits(const IRGenModule &IGM) {
28+
static uint8_t getNumLowObjCReservedBits(const IRGenModule &IGM) {
2929
if (!IGM.ObjCInterop)
3030
return 0;
3131

@@ -34,16 +34,25 @@ static unsigned getNumLowObjCReservedBits(const IRGenModule &IGM) {
3434
return mask.asAPInt().countTrailingOnes();
3535
}
3636

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+
3745
/*****************************************************************************/
3846

3947
/// Return the number of extra inhabitants for a pointer that reserves
4048
/// the given number of low bits.
41-
static unsigned getPointerExtraInhabitantCount(const IRGenModule &IGM,
42-
unsigned numReservedLowBits) {
49+
unsigned PointerInfo::getExtraInhabitantCount(const IRGenModule &IGM) const {
4350
// FIXME: We could also make extra inhabitants using spare bits, but we
4451
// probably don't need to.
4552
uint64_t rawCount =
46-
IGM.TargetInfo.LeastValidPointerValue >> numReservedLowBits;
53+
IGM.TargetInfo.LeastValidPointerValue >> NumReservedLowBits;
54+
55+
if (Nullable) rawCount--;
4756

4857
// The runtime limits the count.
4958
return std::min(uint64_t(ValueWitnessFlags::MaxNumExtraInhabitants),
@@ -54,35 +63,23 @@ unsigned irgen::getHeapObjectExtraInhabitantCount(const IRGenModule &IGM) {
5463
// This must be consistent with the extra inhabitant count produced
5564
// by the runtime's getHeapObjectExtraInhabitantCount function in
5665
// 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);
7267
}
7368

7469
/*****************************************************************************/
7570

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 {
8075
unsigned pointerSizeInBits = IGM.getPointerSize().getValueInBits();
81-
assert(index < getPointerExtraInhabitantCount(IGM, numReservedLowBits) &&
76+
assert(index < getExtraInhabitantCount(IGM) &&
8277
"pointer extra inhabitant out of bounds");
8378
assert(bits >= pointerSizeInBits + offset);
8479

85-
uint64_t value = (uint64_t)index << numReservedLowBits;
80+
if (Nullable) index++;
81+
82+
uint64_t value = (uint64_t)index << NumReservedLowBits;
8683

8784
auto valueBits = BitPatternBuilder(IGM.Triple.isLittleEndian());
8885
valueBits.appendClearBits(offset);
@@ -98,30 +95,14 @@ APInt irgen::getHeapObjectFixedExtraInhabitantValue(const IRGenModule &IGM,
9895
// This must be consistent with the extra inhabitant calculation implemented
9996
// in the runtime's storeHeapObjectExtraInhabitant and
10097
// 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);
118100
}
119101

120102
/*****************************************************************************/
121103

122-
static llvm::Value *getPointerExtraInhabitantIndex(IRGenFunction &IGF,
123-
Address src,
124-
unsigned numReservedLowBits) {
104+
llvm::Value *PointerInfo::getExtraInhabitantIndex(IRGenFunction &IGF,
105+
Address src) const {
125106
llvm::BasicBlock *contBB = IGF.createBasicBlock("is-valid-pointer");
126107
SmallVector<std::pair<llvm::BasicBlock*, llvm::Value*>, 3> phiValues;
127108
auto invalidIndex = llvm::ConstantInt::getSigned(IGF.IGM.Int32Ty, -1);
@@ -140,12 +121,22 @@ static llvm::Value *getPointerExtraInhabitantIndex(IRGenFunction &IGF,
140121
IGF.Builder.CreateCondBr(isValid, contBB, invalidBB);
141122
IGF.Builder.emitBlock(invalidBB);
142123
}
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+
144135
// Check if the inhabitant has any reserved low bits set.
145136
// FIXME: This check is unneeded if the type is known to be pure Swift.
146-
if (numReservedLowBits) {
137+
if (NumReservedLowBits) {
147138
auto objcMask =
148-
llvm::ConstantInt::get(IGF.IGM.SizeTy, (1 << numReservedLowBits) - 1);
139+
llvm::ConstantInt::get(IGF.IGM.SizeTy, (1 << NumReservedLowBits) - 1);
149140
llvm::Value *masked = IGF.Builder.CreateAnd(val, objcMask);
150141
llvm::Value *maskedZero = IGF.Builder.CreateICmpEQ(masked,
151142
llvm::ConstantInt::get(IGF.IGM.SizeTy, 0));
@@ -155,15 +146,20 @@ static llvm::Value *getPointerExtraInhabitantIndex(IRGenFunction &IGF,
155146
IGF.Builder.CreateCondBr(maskedZero, untaggedBB, contBB);
156147
IGF.Builder.emitBlock(untaggedBB);
157148
}
158-
149+
159150
// The inhabitant is an invalid pointer. Derive its extra inhabitant index.
160151
{
161152
llvm::Value *index = val;
162153

163154
// 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)));
167163
}
168164

169165
// Truncate down to i32 if necessary.
@@ -189,34 +185,25 @@ llvm::Value *irgen::getHeapObjectExtraInhabitantIndex(IRGenFunction &IGF,
189185
// This must be consistent with the extra inhabitant calculation implemented
190186
// in the runtime's getHeapObjectExtraInhabitantIndex function in
191187
// 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);
205189
}
206190

207191
/*****************************************************************************/
208192

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 {
213196
if (index->getType() != IGF.IGM.SizeTy) {
214197
index = IGF.Builder.CreateZExt(index, IGF.IGM.SizeTy);
215198
}
216199

217-
if (numReservedLowBits) {
200+
if (Nullable) {
201+
index = IGF.Builder.CreateAdd(index, IGF.IGM.getSize(Size(1)));
202+
}
203+
204+
if (NumReservedLowBits) {
218205
index = IGF.Builder.CreateShl(index,
219-
llvm::ConstantInt::get(IGF.IGM.SizeTy, numReservedLowBits));
206+
llvm::ConstantInt::get(IGF.IGM.SizeTy, NumReservedLowBits));
220207
}
221208

222209
dest = IGF.Builder.CreateBitCast(dest, IGF.IGM.SizeTy->getPointerTo());
@@ -229,19 +216,6 @@ void irgen::storeHeapObjectExtraInhabitant(IRGenFunction &IGF,
229216
// This must be consistent with the extra inhabitant calculation implemented
230217
// in the runtime's storeHeapObjectExtraInhabitant function in
231218
// 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);
247221
}

lib/IRGen/ExtraInhabitants.h

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

20+
#include "IRGen.h"
21+
2022
namespace llvm {
2123
class APInt;
2224
class ConstantInt;
@@ -31,6 +33,60 @@ class Alignment;
3133
class IRGenFunction;
3234
class IRGenModule;
3335

36+
/// Whether the zero pointer is a valid value (i.e. not a valid
37+
/// extra inhabitant) of a particular pointer type.
38+
enum IsNullable_t: bool {
39+
IsNotNullable = false,
40+
IsNullable = true
41+
};
42+
43+
/// Information about a particular pointer type.
44+
struct PointerInfo {
45+
Alignment PointeeAlign;
46+
uint8_t NumReservedLowBits;
47+
IsNullable_t Nullable;
48+
49+
static PointerInfo forHeapObject(const IRGenModule &IGM);
50+
static PointerInfo forFunction(const IRGenModule &IGM);
51+
static PointerInfo forAligned(Alignment pointeeAlign) {
52+
return {pointeeAlign, 0, IsNotNullable};
53+
}
54+
55+
PointerInfo withNullable(IsNullable_t nullable) const {
56+
return {PointeeAlign, NumReservedLowBits, nullable};
57+
}
58+
59+
/// Return the number of extra inhabitant representations for
60+
/// pointers with these properties: i.e. the number of values
61+
/// that do not collide with any valid pointers.
62+
unsigned getExtraInhabitantCount(const IRGenModule &IGM) const;
63+
64+
65+
/// Return an indexed extra inhabitant constant for a pointer
66+
/// with these properties.
67+
///
68+
/// If the pointer appears within a larger aggregate, the
69+
/// 'bits' and 'offset' arguments can be used to position
70+
/// the inhabitant within the larger integer constant.
71+
llvm::APInt getFixedExtraInhabitantValue(const IRGenModule &IGM,
72+
unsigned bits,
73+
unsigned index,
74+
unsigned offset) const;
75+
76+
/// Given the address of storage for a pointer with these
77+
/// properties, return the extra inhabitant index of the
78+
/// value, or -1 if the value is a valid pointer. Always
79+
/// produces an i32.
80+
llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
81+
Address src) const;
82+
83+
/// Store an extra inhabitant representation for the given
84+
/// dynamic extra inhabitant index into the given storage.
85+
void storeExtraInhabitant(IRGenFunction &IGF,
86+
llvm::Value *index,
87+
Address dest) const;
88+
};
89+
3490
/*****************************************************************************/
3591

3692
/// \group Extra inhabitants of heap object pointers.
@@ -61,69 +117,6 @@ void storeHeapObjectExtraInhabitant(IRGenFunction &IGF,
61117
llvm::Value *index,
62118
Address dest);
63119

64-
/*****************************************************************************/
65-
66-
/// \group Extra inhabitants of aligned object pointers.
67-
68-
/// Return the number of extra inhabitant representations for aligned
69-
/// object pointers.
70-
unsigned getAlignedPointerExtraInhabitantCount(IRGenModule &IGM,
71-
Alignment pointeeAlign);
72-
73-
/// Return an indexed extra inhabitant constant for an aligned pointer.
74-
///
75-
/// If the pointer appears within a larger aggregate, the 'bits' and 'offset'
76-
/// arguments can be used to position the inhabitant within the larger integer
77-
/// constant.
78-
llvm::APInt getAlignedPointerExtraInhabitantValue(IRGenModule &IGM,
79-
Alignment pointeeAlign,
80-
unsigned bits,
81-
unsigned index,
82-
unsigned offset);
83-
84-
/// Calculate the index of an aligned pointer extra inhabitant
85-
/// representation stored in memory.
86-
llvm::Value *getAlignedPointerExtraInhabitantIndex(IRGenFunction &IGF,
87-
Alignment pointeeAlign,
88-
Address src);
89-
90-
/// Calculate an extra inhabitant representation from an index and store it to
91-
/// memory.
92-
void storeAlignedPointerExtraInhabitant(IRGenFunction &IGF,
93-
Alignment pointeeAlign,
94-
llvm::Value *index,
95-
Address dest);
96-
97-
/*****************************************************************************/
98-
99-
/// \group Extra inhabitants of function pointers.
100-
101-
/// Return the number of extra inhabitant representations for function pointers,
102-
/// that is, the number of invalid function pointer values that can be used
103-
/// to represent enum tags for enums involving a reference type as a payload.
104-
unsigned getFunctionPointerExtraInhabitantCount(IRGenModule &IGM);
105-
106-
/// Return an indexed extra inhabitant constant for a function pointer.
107-
///
108-
/// If the pointer appears within a larger aggregate, the 'bits' and 'offset'
109-
/// arguments can be used to position the inhabitant within the larger integer
110-
/// constant.
111-
llvm::APInt getFunctionPointerFixedExtraInhabitantValue(IRGenModule &IGM,
112-
unsigned bits,
113-
unsigned index,
114-
unsigned offset);
115-
116-
/// Calculate the index of a function pointer extra inhabitant
117-
/// representation stored in memory.
118-
llvm::Value *getFunctionPointerExtraInhabitantIndex(IRGenFunction &IGF,
119-
Address src);
120-
121-
/// Calculate an extra inhabitant representation from an index and
122-
/// store it to memory.
123-
void storeFunctionPointerExtraInhabitant(IRGenFunction &IGF,
124-
llvm::Value *index,
125-
Address dest);
126-
127120
} // end namespace irgen
128121
} // end namespace swift
129122

0 commit comments

Comments
 (0)