|
22 | 22 | #include "GenTuple.h"
|
23 | 23 | #include "TypeInfo.h"
|
24 | 24 | #include "StructLayout.h"
|
| 25 | +#include "Callee.h" |
25 | 26 | #include "swift/Basic/Range.h"
|
26 | 27 | #include "swift/SIL/SILModule.h"
|
27 | 28 |
|
@@ -109,11 +110,67 @@ llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
|
109 | 110 | llvm_unreachable("bad string encoding");
|
110 | 111 | }
|
111 | 112 |
|
112 |
| -static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) { |
| 113 | +namespace { |
| 114 | + |
| 115 | +/// Fill in the missing values for padding. |
| 116 | +void insertPadding(SmallVectorImpl<llvm::Constant *> &Elements, |
| 117 | + llvm::StructType *sTy) { |
| 118 | + // fill in any gaps, which are the explicit padding that swiftc inserts. |
| 119 | + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { |
| 120 | + auto &elt = Elements[i]; |
| 121 | + if (elt == nullptr) { |
| 122 | + auto *eltTy = sTy->getElementType(i); |
| 123 | + assert(eltTy->isArrayTy() && |
| 124 | + eltTy->getArrayElementType()->isIntegerTy(8) && |
| 125 | + "Unexpected non-byte-array type for constant struct padding"); |
| 126 | + elt = llvm::UndefValue::get(eltTy); |
| 127 | + } |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +template <typename InstTy, typename NextIndexFunc> |
| 132 | +llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst, |
| 133 | + NextIndexFunc nextIndex) { |
| 134 | + auto type = inst->getType(); |
| 135 | + auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType()); |
| 136 | + |
| 137 | + SmallVector<llvm::Constant *, 32> elts(sTy->getNumElements(), nullptr); |
| 138 | + |
| 139 | + // run over the Swift initializers, putting them into the struct as |
| 140 | + // appropriate. |
| 141 | + for (unsigned i = 0, e = inst->getElements().size(); i != e; ++i) { |
| 142 | + auto operand = inst->getOperand(i); |
| 143 | + Optional<unsigned> index = nextIndex(IGM, type, i); |
| 144 | + if (index.hasValue()) { |
| 145 | + assert(elts[index.getValue()] == nullptr && |
| 146 | + "Unexpected constant struct field overlap"); |
| 147 | + |
| 148 | + elts[index.getValue()] = emitConstantValue(IGM, operand); |
| 149 | + } |
| 150 | + } |
| 151 | + insertPadding(elts, sTy); |
| 152 | + return llvm::ConstantStruct::get(sTy, elts); |
| 153 | +} |
| 154 | +} // end anonymous namespace |
| 155 | + |
| 156 | +llvm::Constant *irgen::emitConstantValue(IRGenModule &IGM, SILValue operand) { |
113 | 157 | if (auto *SI = dyn_cast<StructInst>(operand)) {
|
114 |
| - return emitConstantStruct(IGM, SI); |
| 158 | + // The only way to get a struct's stored properties (which we need to map to |
| 159 | + // their physical/LLVM index) is to iterate over the properties |
| 160 | + // progressively. Fortunately the iteration order matches the order of |
| 161 | + // operands in a StructInst. |
| 162 | + auto StoredProperties = SI->getStructDecl()->getStoredProperties(); |
| 163 | + auto Iter = StoredProperties.begin(); |
| 164 | + |
| 165 | + return emitConstantStructOrTuple( |
| 166 | + IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable { |
| 167 | + (void)_i; |
| 168 | + auto *FD = *Iter++; |
| 169 | + return irgen::getPhysicalStructFieldIndex(IGM, Type, FD); |
| 170 | + }); |
115 | 171 | } else if (auto *TI = dyn_cast<TupleInst>(operand)) {
|
116 |
| - return emitConstantTuple(IGM, TI); |
| 172 | + return emitConstantStructOrTuple(IGM, TI, |
| 173 | + irgen::getPhysicalTupleElementStructIndex); |
117 | 174 | } else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand)) {
|
118 | 175 | return emitConstantInt(IGM, ILI);
|
119 | 176 | } else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand)) {
|
@@ -164,70 +221,6 @@ static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
|
164 | 221 | }
|
165 | 222 | }
|
166 | 223 |
|
167 |
| -namespace { |
168 |
| - |
169 |
| -/// Fill in the missing values for padding. |
170 |
| -void insertPadding(SmallVectorImpl<llvm::Constant *> &Elements, |
171 |
| - llvm::StructType *sTy) { |
172 |
| - // fill in any gaps, which are the explicit padding that swiftc inserts. |
173 |
| - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { |
174 |
| - auto &elt = Elements[i]; |
175 |
| - if (elt == nullptr) { |
176 |
| - auto *eltTy = sTy->getElementType(i); |
177 |
| - assert(eltTy->isArrayTy() && |
178 |
| - eltTy->getArrayElementType()->isIntegerTy(8) && |
179 |
| - "Unexpected non-byte-array type for constant struct padding"); |
180 |
| - elt = llvm::UndefValue::get(eltTy); |
181 |
| - } |
182 |
| - } |
183 |
| -} |
184 |
| - |
185 |
| -template <typename InstTy, typename NextIndexFunc> |
186 |
| -llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst, |
187 |
| - NextIndexFunc nextIndex) { |
188 |
| - auto type = inst->getType(); |
189 |
| - auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType()); |
190 |
| - |
191 |
| - SmallVector<llvm::Constant *, 32> elts(sTy->getNumElements(), nullptr); |
192 |
| - |
193 |
| - // run over the Swift initializers, putting them into the struct as |
194 |
| - // appropriate. |
195 |
| - for (unsigned i = 0, e = inst->getElements().size(); i != e; ++i) { |
196 |
| - auto operand = inst->getOperand(i); |
197 |
| - Optional<unsigned> index = nextIndex(IGM, type, i); |
198 |
| - if (index.hasValue()) { |
199 |
| - assert(elts[index.getValue()] == nullptr && |
200 |
| - "Unexpected constant struct field overlap"); |
201 |
| - |
202 |
| - elts[index.getValue()] = emitConstantValue(IGM, operand); |
203 |
| - } |
204 |
| - } |
205 |
| - insertPadding(elts, sTy); |
206 |
| - return llvm::ConstantStruct::get(sTy, elts); |
207 |
| -} |
208 |
| -} // end anonymous namespace |
209 |
| - |
210 |
| -llvm::Constant *irgen::emitConstantStruct(IRGenModule &IGM, StructInst *SI) { |
211 |
| - // The only way to get a struct's stored properties (which we need to map to |
212 |
| - // their physical/LLVM index) is to iterate over the properties |
213 |
| - // progressively. Fortunately the iteration order matches the order of |
214 |
| - // operands in a StructInst. |
215 |
| - auto StoredProperties = SI->getStructDecl()->getStoredProperties(); |
216 |
| - auto Iter = StoredProperties.begin(); |
217 |
| - |
218 |
| - return emitConstantStructOrTuple( |
219 |
| - IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable { |
220 |
| - (void)_i; |
221 |
| - auto *FD = *Iter++; |
222 |
| - return irgen::getPhysicalStructFieldIndex(IGM, Type, FD); |
223 |
| - }); |
224 |
| -} |
225 |
| - |
226 |
| -llvm::Constant *irgen::emitConstantTuple(IRGenModule &IGM, TupleInst *TI) { |
227 |
| - return emitConstantStructOrTuple(IGM, TI, |
228 |
| - irgen::getPhysicalTupleElementStructIndex); |
229 |
| -} |
230 |
| - |
231 | 224 | llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
|
232 | 225 | StructLayout *ClassLayout) {
|
233 | 226 | auto *sTy = cast<llvm::StructType>(ClassLayout->getType());
|
|
0 commit comments