1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/CodeGen/SwiftCallingConv.h" |
14 | #include "clang/Basic/TargetInfo.h" |
15 | #include "CodeGenModule.h" |
16 | #include "TargetInfo.h" |
17 | |
18 | using namespace clang; |
19 | using namespace CodeGen; |
20 | using namespace swiftcall; |
21 | |
22 | static const SwiftABIInfo &getSwiftABIInfo(CodeGenModule &CGM) { |
23 | return cast<SwiftABIInfo>(CGM.getTargetCodeGenInfo().getABIInfo()); |
24 | } |
25 | |
26 | static bool isPowerOf2(unsigned n) { |
27 | return n == (n & -n); |
28 | } |
29 | |
30 | |
31 | static llvm::Type *getCommonType(llvm::Type *first, llvm::Type *second) { |
32 | assert(first != second); |
33 | |
34 | |
35 | if (first->isIntegerTy()) { |
36 | if (second->isPointerTy()) return first; |
37 | } else if (first->isPointerTy()) { |
38 | if (second->isIntegerTy()) return second; |
39 | if (second->isPointerTy()) return first; |
40 | |
41 | |
42 | |
43 | } else if (auto firstVecTy = dyn_cast<llvm::VectorType>(first)) { |
44 | if (auto secondVecTy = dyn_cast<llvm::VectorType>(second)) { |
45 | if (auto commonTy = getCommonType(firstVecTy->getElementType(), |
46 | secondVecTy->getElementType())) { |
47 | return (commonTy == firstVecTy->getElementType() ? first : second); |
48 | } |
49 | } |
50 | } |
51 | |
52 | return nullptr; |
53 | } |
54 | |
55 | static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type) { |
56 | return CharUnits::fromQuantity(CGM.getDataLayout().getTypeStoreSize(type)); |
57 | } |
58 | |
59 | static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type) { |
60 | return CharUnits::fromQuantity(CGM.getDataLayout().getTypeAllocSize(type)); |
61 | } |
62 | |
63 | void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { |
64 | |
65 | |
66 | |
67 | if (auto recType = type->getAs<RecordType>()) { |
68 | addTypedData(recType->getDecl(), begin); |
69 | |
70 | |
71 | } else if (type->isArrayType()) { |
72 | |
73 | |
74 | auto arrayType = CGM.getContext().getAsConstantArrayType(type); |
75 | if (!arrayType) return; |
76 | |
77 | QualType eltType = arrayType->getElementType(); |
78 | auto eltSize = CGM.getContext().getTypeSizeInChars(eltType); |
79 | for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) { |
80 | addTypedData(eltType, begin + i * eltSize); |
81 | } |
82 | |
83 | |
84 | } else if (auto complexType = type->getAs<ComplexType>()) { |
85 | auto eltType = complexType->getElementType(); |
86 | auto eltSize = CGM.getContext().getTypeSizeInChars(eltType); |
87 | auto eltLLVMType = CGM.getTypes().ConvertType(eltType); |
88 | addTypedData(eltLLVMType, begin, begin + eltSize); |
89 | addTypedData(eltLLVMType, begin + eltSize, begin + 2 * eltSize); |
90 | |
91 | |
92 | } else if (type->getAs<MemberPointerType>()) { |
93 | |
94 | addOpaqueData(begin, begin + CGM.getContext().getTypeSizeInChars(type)); |
95 | |
96 | |
97 | } else { |
98 | |
99 | |
100 | auto llvmType = CGM.getTypes().ConvertType(type); |
101 | addTypedData(llvmType, begin); |
102 | } |
103 | } |
104 | |
105 | void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin) { |
106 | addTypedData(record, begin, CGM.getContext().getASTRecordLayout(record)); |
107 | } |
108 | |
109 | void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin, |
110 | const ASTRecordLayout &layout) { |
111 | |
112 | if (record->isUnion()) { |
113 | for (auto field : record->fields()) { |
114 | if (field->isBitField()) { |
115 | addBitFieldData(field, begin, 0); |
116 | } else { |
117 | addTypedData(field->getType(), begin); |
118 | } |
119 | } |
120 | return; |
121 | } |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | auto cxxRecord = dyn_cast<CXXRecordDecl>(record); |
129 | if (cxxRecord) { |
130 | |
131 | if (layout.hasOwnVFPtr()) { |
132 | addTypedData(CGM.Int8PtrTy, begin); |
133 | } |
134 | |
135 | |
136 | for (auto &baseSpecifier : cxxRecord->bases()) { |
137 | if (baseSpecifier.isVirtual()) continue; |
138 | |
139 | auto baseRecord = baseSpecifier.getType()->getAsCXXRecordDecl(); |
140 | addTypedData(baseRecord, begin + layout.getBaseClassOffset(baseRecord)); |
141 | } |
142 | |
143 | |
144 | if (layout.hasOwnVBPtr()) { |
145 | addTypedData(CGM.Int8PtrTy, begin + layout.getVBPtrOffset()); |
146 | } |
147 | } |
148 | |
149 | |
150 | for (auto field : record->fields()) { |
151 | auto fieldOffsetInBits = layout.getFieldOffset(field->getFieldIndex()); |
152 | if (field->isBitField()) { |
153 | addBitFieldData(field, begin, fieldOffsetInBits); |
154 | } else { |
155 | addTypedData(field->getType(), |
156 | begin + CGM.getContext().toCharUnitsFromBits(fieldOffsetInBits)); |
157 | } |
158 | } |
159 | |
160 | |
161 | if (cxxRecord) { |
162 | |
163 | for (auto &vbaseSpecifier : cxxRecord->vbases()) { |
164 | auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl(); |
165 | addTypedData(baseRecord, begin + layout.getVBaseClassOffset(baseRecord)); |
166 | } |
167 | } |
168 | } |
169 | |
170 | void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield, |
171 | CharUnits recordBegin, |
172 | uint64_t bitfieldBitBegin) { |
173 | isBitField()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 173, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(bitfield->isBitField()); |
174 | auto &ctx = CGM.getContext(); |
175 | auto width = bitfield->getBitWidthValue(ctx); |
176 | |
177 | |
178 | if (width == 0) return; |
179 | |
180 | |
181 | CharUnits bitfieldByteBegin = ctx.toCharUnitsFromBits(bitfieldBitBegin); |
182 | |
183 | |
184 | |
185 | |
186 | uint64_t bitfieldBitLast = bitfieldBitBegin + width - 1; |
187 | CharUnits bitfieldByteEnd = |
188 | ctx.toCharUnitsFromBits(bitfieldBitLast) + CharUnits::One(); |
189 | addOpaqueData(recordBegin + bitfieldByteBegin, |
190 | recordBegin + bitfieldByteEnd); |
191 | } |
192 | |
193 | void SwiftAggLowering::addTypedData(llvm::Type *type, CharUnits begin) { |
194 | (0) . __assert_fail ("type && \"didn't provide type for typed data\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 194, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(type && "didn't provide type for typed data"); |
195 | addTypedData(type, begin, begin + getTypeStoreSize(CGM, type)); |
196 | } |
197 | |
198 | void SwiftAggLowering::addTypedData(llvm::Type *type, |
199 | CharUnits begin, CharUnits end) { |
200 | (0) . __assert_fail ("type && \"didn't provide type for typed data\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 200, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(type && "didn't provide type for typed data"); |
201 | assert(getTypeStoreSize(CGM, type) == end - begin); |
202 | |
203 | |
204 | if (auto vecTy = dyn_cast<llvm::VectorType>(type)) { |
205 | SmallVector<llvm::Type*, 4> componentTys; |
206 | legalizeVectorType(CGM, end - begin, vecTy, componentTys); |
207 | = 1", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 207, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(componentTys.size() >= 1); |
208 | |
209 | |
210 | for (size_t i = 0, e = componentTys.size(); i != e - 1; ++i) { |
211 | llvm::Type *componentTy = componentTys[i]; |
212 | auto componentSize = getTypeStoreSize(CGM, componentTy); |
213 | assert(componentSize < end - begin); |
214 | addLegalTypedData(componentTy, begin, begin + componentSize); |
215 | begin += componentSize; |
216 | } |
217 | |
218 | return addLegalTypedData(componentTys.back(), begin, end); |
219 | } |
220 | |
221 | |
222 | if (auto intTy = dyn_cast<llvm::IntegerType>(type)) { |
223 | if (!isLegalIntegerType(CGM, intTy)) |
224 | return addOpaqueData(begin, end); |
225 | } |
226 | |
227 | |
228 | return addLegalTypedData(type, begin, end); |
229 | } |
230 | |
231 | void SwiftAggLowering::addLegalTypedData(llvm::Type *type, |
232 | CharUnits begin, CharUnits end) { |
233 | |
234 | if (!begin.isZero() && !begin.isMultipleOf(getNaturalAlignment(CGM, type))) { |
235 | |
236 | |
237 | if (auto vecTy = dyn_cast<llvm::VectorType>(type)) { |
238 | auto split = splitLegalVectorType(CGM, end - begin, vecTy); |
239 | auto eltTy = split.first; |
240 | auto numElts = split.second; |
241 | |
242 | auto eltSize = (end - begin) / numElts; |
243 | assert(eltSize == getTypeStoreSize(CGM, eltTy)); |
244 | for (size_t i = 0, e = numElts; i != e; ++i) { |
245 | addLegalTypedData(eltTy, begin, begin + eltSize); |
246 | begin += eltSize; |
247 | } |
248 | assert(begin == end); |
249 | return; |
250 | } |
251 | |
252 | return addOpaqueData(begin, end); |
253 | } |
254 | |
255 | addEntry(type, begin, end); |
256 | } |
257 | |
258 | void SwiftAggLowering::addEntry(llvm::Type *type, |
259 | CharUnits begin, CharUnits end) { |
260 | (0) . __assert_fail ("(!type || (!isa(type) && !isa(type))) && \"cannot add aggregate-typed data\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 262, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((!type || |
261 | (0) . __assert_fail ("(!type || (!isa(type) && !isa(type))) && \"cannot add aggregate-typed data\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 262, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) && |
262 | (0) . __assert_fail ("(!type || (!isa(type) && !isa(type))) && \"cannot add aggregate-typed data\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 262, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "cannot add aggregate-typed data"); |
263 | assert(!type || begin.isMultipleOf(getNaturalAlignment(CGM, type))); |
264 | |
265 | |
266 | if (Entries.empty() || Entries.back().End <= begin) { |
267 | Entries.push_back({begin, end, type}); |
268 | return; |
269 | } |
270 | |
271 | |
272 | |
273 | size_t index = Entries.size() - 1; |
274 | while (index != 0) { |
275 | if (Entries[index - 1].End <= begin) break; |
276 | --index; |
277 | } |
278 | |
279 | |
280 | |
281 | if (Entries[index].Begin >= end) { |
282 | |
283 | |
284 | |
285 | Entries.insert(Entries.begin() + index, {begin, end, type}); |
286 | return; |
287 | } |
288 | |
289 | |
290 | |
291 | restartAfterSplit: |
292 | |
293 | |
294 | if (Entries[index].Begin == begin && Entries[index].End == end) { |
295 | |
296 | if (Entries[index].Type == type) return; |
297 | |
298 | |
299 | if (Entries[index].Type == nullptr) { |
300 | return; |
301 | } else if (type == nullptr) { |
302 | Entries[index].Type = nullptr; |
303 | return; |
304 | } |
305 | |
306 | |
307 | |
308 | if (auto entryType = getCommonType(Entries[index].Type, type)) { |
309 | Entries[index].Type = entryType; |
310 | return; |
311 | } |
312 | |
313 | |
314 | Entries[index].Type = nullptr; |
315 | return; |
316 | } |
317 | |
318 | |
319 | |
320 | |
321 | if (auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) { |
322 | auto eltTy = vecTy->getElementType(); |
323 | CharUnits eltSize = (end - begin) / vecTy->getNumElements(); |
324 | assert(eltSize == getTypeStoreSize(CGM, eltTy)); |
325 | for (unsigned i = 0, e = vecTy->getNumElements(); i != e; ++i) { |
326 | addEntry(eltTy, begin, begin + eltSize); |
327 | begin += eltSize; |
328 | } |
329 | assert(begin == end); |
330 | return; |
331 | } |
332 | |
333 | |
334 | if (Entries[index].Type && Entries[index].Type->isVectorTy()) { |
335 | splitVectorEntry(index); |
336 | goto restartAfterSplit; |
337 | } |
338 | |
339 | |
340 | |
341 | Entries[index].Type = nullptr; |
342 | |
343 | |
344 | if (begin < Entries[index].Begin) { |
345 | Entries[index].Begin = begin; |
346 | = Entries[index - 1].End", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 346, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(index == 0 || begin >= Entries[index - 1].End); |
347 | } |
348 | |
349 | |
350 | |
351 | while (end > Entries[index].End) { |
352 | assert(Entries[index].Type == nullptr); |
353 | |
354 | |
355 | if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) { |
356 | Entries[index].End = end; |
357 | break; |
358 | } |
359 | |
360 | |
361 | Entries[index].End = Entries[index + 1].Begin; |
362 | |
363 | |
364 | index++; |
365 | |
366 | |
367 | if (Entries[index].Type == nullptr) |
368 | continue; |
369 | |
370 | |
371 | if (Entries[index].Type->isVectorTy() && |
372 | end < Entries[index].End) { |
373 | splitVectorEntry(index); |
374 | } |
375 | |
376 | |
377 | Entries[index].Type = nullptr; |
378 | } |
379 | } |
380 | |
381 | |
382 | |
383 | void SwiftAggLowering::splitVectorEntry(unsigned index) { |
384 | auto vecTy = cast<llvm::VectorType>(Entries[index].Type); |
385 | auto split = splitLegalVectorType(CGM, Entries[index].getWidth(), vecTy); |
386 | |
387 | auto eltTy = split.first; |
388 | CharUnits eltSize = getTypeStoreSize(CGM, eltTy); |
389 | auto numElts = split.second; |
390 | Entries.insert(Entries.begin() + index + 1, numElts - 1, StorageEntry()); |
391 | |
392 | CharUnits begin = Entries[index].Begin; |
393 | for (unsigned i = 0; i != numElts; ++i) { |
394 | Entries[index].Type = eltTy; |
395 | Entries[index].Begin = begin; |
396 | Entries[index].End = begin + eltSize; |
397 | begin += eltSize; |
398 | } |
399 | } |
400 | |
401 | |
402 | |
403 | |
404 | |
405 | static CharUnits getOffsetAtStartOfUnit(CharUnits offset, CharUnits unitSize) { |
406 | assert(isPowerOf2(unitSize.getQuantity())); |
407 | auto unitMask = ~(unitSize.getQuantity() - 1); |
408 | return CharUnits::fromQuantity(offset.getQuantity() & unitMask); |
409 | } |
410 | |
411 | static bool areBytesInSameUnit(CharUnits first, CharUnits second, |
412 | CharUnits chunkSize) { |
413 | return getOffsetAtStartOfUnit(first, chunkSize) |
414 | == getOffsetAtStartOfUnit(second, chunkSize); |
415 | } |
416 | |
417 | static bool isMergeableEntryType(llvm::Type *type) { |
418 | |
419 | if (type == nullptr) return true; |
420 | |
421 | |
422 | |
423 | |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | |
434 | return (!type->isFloatingPointTy() && !type->isVectorTy()); |
435 | } |
436 | |
437 | bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first, |
438 | const StorageEntry &second, |
439 | CharUnits chunkSize) { |
440 | |
441 | |
442 | |
443 | if (!areBytesInSameUnit(first.End - CharUnits::One(), second.Begin, |
444 | chunkSize)) |
445 | return false; |
446 | |
447 | return (isMergeableEntryType(first.Type) && |
448 | isMergeableEntryType(second.Type)); |
449 | } |
450 | |
451 | void SwiftAggLowering::finish() { |
452 | if (Entries.empty()) { |
453 | Finished = true; |
454 | return; |
455 | } |
456 | |
457 | |
458 | |
459 | const CharUnits chunkSize = getMaximumVoluntaryIntegerSize(CGM); |
460 | |
461 | |
462 | |
463 | |
464 | bool hasOpaqueEntries = (Entries[0].Type == nullptr); |
465 | for (size_t i = 1, e = Entries.size(); i != e; ++i) { |
466 | if (shouldMergeEntries(Entries[i - 1], Entries[i], chunkSize)) { |
467 | Entries[i - 1].Type = nullptr; |
468 | Entries[i].Type = nullptr; |
469 | Entries[i - 1].End = Entries[i].Begin; |
470 | hasOpaqueEntries = true; |
471 | |
472 | } else if (Entries[i].Type == nullptr) { |
473 | hasOpaqueEntries = true; |
474 | } |
475 | } |
476 | |
477 | |
478 | |
479 | if (!hasOpaqueEntries) { |
480 | Finished = true; |
481 | return; |
482 | } |
483 | |
484 | |
485 | auto orig = std::move(Entries); |
486 | assert(Entries.empty()); |
487 | |
488 | for (size_t i = 0, e = orig.size(); i != e; ++i) { |
489 | |
490 | if (orig[i].Type != nullptr) { |
491 | Entries.push_back(orig[i]); |
492 | continue; |
493 | } |
494 | |
495 | |
496 | |
497 | |
498 | auto begin = orig[i].Begin; |
499 | auto end = orig[i].End; |
500 | while (i + 1 != e && |
501 | orig[i + 1].Type == nullptr && |
502 | end == orig[i + 1].Begin) { |
503 | end = orig[i + 1].End; |
504 | i++; |
505 | } |
506 | |
507 | |
508 | do { |
509 | |
510 | |
511 | |
512 | CharUnits localBegin = begin; |
513 | CharUnits chunkBegin = getOffsetAtStartOfUnit(localBegin, chunkSize); |
514 | CharUnits chunkEnd = chunkBegin + chunkSize; |
515 | CharUnits localEnd = std::min(end, chunkEnd); |
516 | |
517 | |
518 | CharUnits unitSize = CharUnits::One(); |
519 | CharUnits unitBegin, unitEnd; |
520 | for (; ; unitSize *= 2) { |
521 | assert(unitSize <= chunkSize); |
522 | unitBegin = getOffsetAtStartOfUnit(localBegin, unitSize); |
523 | unitEnd = unitBegin + unitSize; |
524 | if (unitEnd >= localEnd) break; |
525 | } |
526 | |
527 | |
528 | auto entryTy = |
529 | llvm::IntegerType::get(CGM.getLLVMContext(), |
530 | CGM.getContext().toBits(unitSize)); |
531 | Entries.push_back({unitBegin, unitEnd, entryTy}); |
532 | |
533 | |
534 | begin = localEnd; |
535 | } while (begin != end); |
536 | } |
537 | |
538 | |
539 | Finished = true; |
540 | } |
541 | |
542 | void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const { |
543 | (0) . __assert_fail ("Finished && \"haven't yet finished lowering\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 543, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Finished && "haven't yet finished lowering"); |
544 | |
545 | for (auto &entry : Entries) { |
546 | callback(entry.Begin, entry.End, entry.Type); |
547 | } |
548 | } |
549 | |
550 | std::pair<llvm::StructType*, llvm::Type*> |
551 | SwiftAggLowering::getCoerceAndExpandTypes() const { |
552 | (0) . __assert_fail ("Finished && \"haven't yet finished lowering\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 552, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Finished && "haven't yet finished lowering"); |
553 | |
554 | auto &ctx = CGM.getLLVMContext(); |
555 | |
556 | if (Entries.empty()) { |
557 | auto type = llvm::StructType::get(ctx); |
558 | return { type, type }; |
559 | } |
560 | |
561 | SmallVector<llvm::Type*, 8> elts; |
562 | CharUnits lastEnd = CharUnits::Zero(); |
563 | bool hasPadding = false; |
564 | bool packed = false; |
565 | for (auto &entry : Entries) { |
566 | if (entry.Begin != lastEnd) { |
567 | auto paddingSize = entry.Begin - lastEnd; |
568 | assert(!paddingSize.isNegative()); |
569 | |
570 | auto padding = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx), |
571 | paddingSize.getQuantity()); |
572 | elts.push_back(padding); |
573 | hasPadding = true; |
574 | } |
575 | |
576 | if (!packed && !entry.Begin.isMultipleOf( |
577 | CharUnits::fromQuantity( |
578 | CGM.getDataLayout().getABITypeAlignment(entry.Type)))) |
579 | packed = true; |
580 | |
581 | elts.push_back(entry.Type); |
582 | |
583 | lastEnd = entry.Begin + getTypeAllocSize(CGM, entry.Type); |
584 | assert(entry.End <= lastEnd); |
585 | } |
586 | |
587 | |
588 | |
589 | auto coercionType = llvm::StructType::get(ctx, elts, packed); |
590 | |
591 | llvm::Type *unpaddedType = coercionType; |
592 | if (hasPadding) { |
593 | elts.clear(); |
594 | for (auto &entry : Entries) { |
595 | elts.push_back(entry.Type); |
596 | } |
597 | if (elts.size() == 1) { |
598 | unpaddedType = elts[0]; |
599 | } else { |
600 | unpaddedType = llvm::StructType::get(ctx, elts, false); |
601 | } |
602 | } else if (Entries.size() == 1) { |
603 | unpaddedType = Entries[0].Type; |
604 | } |
605 | |
606 | return { coercionType, unpaddedType }; |
607 | } |
608 | |
609 | bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const { |
610 | (0) . __assert_fail ("Finished && \"haven't yet finished lowering\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 610, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Finished && "haven't yet finished lowering"); |
611 | |
612 | |
613 | if (Entries.empty()) return false; |
614 | |
615 | |
616 | if (Entries.size() == 1) { |
617 | return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift( |
618 | Entries.back().Type, |
619 | asReturnValue); |
620 | } |
621 | |
622 | SmallVector<llvm::Type*, 8> componentTys; |
623 | componentTys.reserve(Entries.size()); |
624 | for (auto &entry : Entries) { |
625 | componentTys.push_back(entry.Type); |
626 | } |
627 | return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys, |
628 | asReturnValue); |
629 | } |
630 | |
631 | bool swiftcall::shouldPassIndirectly(CodeGenModule &CGM, |
632 | ArrayRef<llvm::Type*> componentTys, |
633 | bool asReturnValue) { |
634 | return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys, |
635 | asReturnValue); |
636 | } |
637 | |
638 | CharUnits swiftcall::getMaximumVoluntaryIntegerSize(CodeGenModule &CGM) { |
639 | |
640 | return CGM.getContext().toCharUnitsFromBits( |
641 | CGM.getContext().getTargetInfo().getPointerWidth(0)); |
642 | } |
643 | |
644 | CharUnits swiftcall::getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type) { |
645 | |
646 | |
647 | auto size = (unsigned long long) getTypeStoreSize(CGM, type).getQuantity(); |
648 | if (!isPowerOf2(size)) { |
649 | size = 1ULL << (llvm::findLastSet(size, llvm::ZB_Undefined) + 1); |
650 | } |
651 | = CGM.getDataLayout().getABITypeAlignment(type)", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 651, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(size >= CGM.getDataLayout().getABITypeAlignment(type)); |
652 | return CharUnits::fromQuantity(size); |
653 | } |
654 | |
655 | bool swiftcall::isLegalIntegerType(CodeGenModule &CGM, |
656 | llvm::IntegerType *intTy) { |
657 | auto size = intTy->getBitWidth(); |
658 | switch (size) { |
659 | case 1: |
660 | case 8: |
661 | case 16: |
662 | case 32: |
663 | case 64: |
664 | |
665 | return true; |
666 | |
667 | case 128: |
668 | return CGM.getContext().getTargetInfo().hasInt128Type(); |
669 | |
670 | default: |
671 | return false; |
672 | } |
673 | } |
674 | |
675 | bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, |
676 | llvm::VectorType *vectorTy) { |
677 | return isLegalVectorType(CGM, vectorSize, vectorTy->getElementType(), |
678 | vectorTy->getNumElements()); |
679 | } |
680 | |
681 | bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, |
682 | llvm::Type *eltTy, unsigned numElts) { |
683 | (0) . __assert_fail ("numElts > 1 && \"illegal vector length\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 683, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(numElts > 1 && "illegal vector length"); |
684 | return getSwiftABIInfo(CGM) |
685 | .isLegalVectorTypeForSwift(vectorSize, eltTy, numElts); |
686 | } |
687 | |
688 | std::pair<llvm::Type*, unsigned> |
689 | swiftcall::splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, |
690 | llvm::VectorType *vectorTy) { |
691 | auto numElts = vectorTy->getNumElements(); |
692 | auto eltTy = vectorTy->getElementType(); |
693 | |
694 | |
695 | if (numElts >= 4 && isPowerOf2(numElts)) { |
696 | if (isLegalVectorType(CGM, vectorSize / 2, eltTy, numElts / 2)) |
697 | return {llvm::VectorType::get(eltTy, numElts / 2), 2}; |
698 | } |
699 | |
700 | return {eltTy, numElts}; |
701 | } |
702 | |
703 | void swiftcall::legalizeVectorType(CodeGenModule &CGM, CharUnits origVectorSize, |
704 | llvm::VectorType *origVectorTy, |
705 | llvm::SmallVectorImpl<llvm::Type*> &components) { |
706 | |
707 | if (isLegalVectorType(CGM, origVectorSize, origVectorTy)) { |
708 | components.push_back(origVectorTy); |
709 | return; |
710 | } |
711 | |
712 | |
713 | auto numElts = origVectorTy->getNumElements(); |
714 | auto eltTy = origVectorTy->getElementType(); |
715 | assert(numElts != 1); |
716 | |
717 | |
718 | |
719 | unsigned logCandidateNumElts = llvm::findLastSet(numElts, llvm::ZB_Undefined); |
720 | unsigned candidateNumElts = 1U << logCandidateNumElts; |
721 | numElts", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/SwiftCallingConv.cpp", 721, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(candidateNumElts <= numElts && candidateNumElts * 2 > numElts); |
722 | |
723 | |
724 | if (candidateNumElts == numElts) { |
725 | logCandidateNumElts--; |
726 | candidateNumElts >>= 1; |
727 | } |
728 | |
729 | CharUnits eltSize = (origVectorSize / numElts); |
730 | CharUnits candidateSize = eltSize * candidateNumElts; |
731 | |
732 | |
733 | |
734 | |
735 | while (logCandidateNumElts > 0) { |
736 | assert(candidateNumElts == 1U << logCandidateNumElts); |
737 | assert(candidateNumElts <= numElts); |
738 | assert(candidateSize == eltSize * candidateNumElts); |
739 | |
740 | |
741 | if (!isLegalVectorType(CGM, candidateSize, eltTy, candidateNumElts)) { |
742 | logCandidateNumElts--; |
743 | candidateNumElts /= 2; |
744 | candidateSize /= 2; |
745 | continue; |
746 | } |
747 | |
748 | |
749 | auto numVecs = numElts >> logCandidateNumElts; |
750 | components.append(numVecs, llvm::VectorType::get(eltTy, candidateNumElts)); |
751 | numElts -= (numVecs << logCandidateNumElts); |
752 | |
753 | if (numElts == 0) return; |
754 | |
755 | |
756 | |
757 | |
758 | if (numElts > 2 && !isPowerOf2(numElts) && |
759 | isLegalVectorType(CGM, eltSize * numElts, eltTy, numElts)) { |
760 | components.push_back(llvm::VectorType::get(eltTy, numElts)); |
761 | return; |
762 | } |
763 | |
764 | |
765 | do { |
766 | logCandidateNumElts--; |
767 | candidateNumElts /= 2; |
768 | candidateSize /= 2; |
769 | } while (candidateNumElts > numElts); |
770 | } |
771 | |
772 | |
773 | components.append(numElts, eltTy); |
774 | } |
775 | |
776 | bool swiftcall::mustPassRecordIndirectly(CodeGenModule &CGM, |
777 | const RecordDecl *record) { |
778 | |
779 | |
780 | |
781 | return !record->canPassInRegisters(); |
782 | } |
783 | |
784 | static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering, |
785 | bool forReturn, |
786 | CharUnits alignmentForIndirect) { |
787 | if (lowering.empty()) { |
788 | return ABIArgInfo::getIgnore(); |
789 | } else if (lowering.shouldPassIndirectly(forReturn)) { |
790 | return ABIArgInfo::getIndirect(alignmentForIndirect, false); |
791 | } else { |
792 | auto types = lowering.getCoerceAndExpandTypes(); |
793 | return ABIArgInfo::getCoerceAndExpand(types.first, types.second); |
794 | } |
795 | } |
796 | |
797 | static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, |
798 | bool forReturn) { |
799 | if (auto recordType = dyn_cast<RecordType>(type)) { |
800 | auto record = recordType->getDecl(); |
801 | auto &layout = CGM.getContext().getASTRecordLayout(record); |
802 | |
803 | if (mustPassRecordIndirectly(CGM, record)) |
804 | return ABIArgInfo::getIndirect(layout.getAlignment(), false); |
805 | |
806 | SwiftAggLowering lowering(CGM); |
807 | lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout); |
808 | lowering.finish(); |
809 | |
810 | return classifyExpandedType(lowering, forReturn, layout.getAlignment()); |
811 | } |
812 | |
813 | |
814 | |
815 | if (isa<ComplexType>(type)) { |
816 | return (forReturn ? ABIArgInfo::getDirect() : ABIArgInfo::getExpand()); |
817 | } |
818 | |
819 | |
820 | if (isa<VectorType>(type)) { |
821 | SwiftAggLowering lowering(CGM); |
822 | lowering.addTypedData(type, CharUnits::Zero()); |
823 | lowering.finish(); |
824 | |
825 | CharUnits alignment = CGM.getContext().getTypeAlignInChars(type); |
826 | return classifyExpandedType(lowering, forReturn, alignment); |
827 | } |
828 | |
829 | |
830 | |
831 | |
832 | |
833 | |
834 | if (type->isVoidType()) { |
835 | return ABIArgInfo::getIgnore(); |
836 | } |
837 | |
838 | |
839 | return ABIArgInfo::getDirect(); |
840 | } |
841 | |
842 | ABIArgInfo swiftcall::classifyReturnType(CodeGenModule &CGM, CanQualType type) { |
843 | return classifyType(CGM, type, true); |
844 | } |
845 | |
846 | ABIArgInfo swiftcall::classifyArgumentType(CodeGenModule &CGM, |
847 | CanQualType type) { |
848 | return classifyType(CGM, type, false); |
849 | } |
850 | |
851 | void swiftcall::computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) { |
852 | auto &retInfo = FI.getReturnInfo(); |
853 | retInfo = classifyReturnType(CGM, FI.getReturnType()); |
854 | |
855 | for (unsigned i = 0, e = FI.arg_size(); i != e; ++i) { |
856 | auto &argInfo = FI.arg_begin()[i]; |
857 | argInfo.info = classifyArgumentType(CGM, argInfo.type); |
858 | } |
859 | } |
860 | |
861 | |
862 | bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) { |
863 | return getSwiftABIInfo(CGM).isSwiftErrorInRegister(); |
864 | } |
865 | |