clang 24.0.0git
CallConvLoweringPass.cpp
Go to the documentation of this file.
1//===- CallConvLoweringPass.cpp - Lower CIR to ABI calling convention ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass walks every cir.func and cir.call in the module, computes a
10// FunctionClassification for it (via either an ABI target or a pre-built
11// classification injected as a function attribute), and dispatches to
12// CIRABIRewriteContext to perform the actual IR rewriting.
13//
14// Two driver modes (mutually exclusive):
15//
16// target=test
17// Use the MLIR test ABI target (mlir/lib/ABI/Targets/Test/) to classify
18// each function. Predictable rules that approximate x86_64 SysV. Real
19// targets (x86_64, AArch64) will be added once the LLVM ABI library
20// ships them.
21//
22// classification-attr=<name>
23// Read a DictionaryAttr named <name> from each cir.func and parse it via
24// mlir::abi::test::parseClassificationAttr. Used by tests to inject any
25// classification (including shapes the test target itself does not
26// produce) without depending on a real ABI target.
27//
28// The pass requires a `dlti.dl_spec` attribute on the module so the
29// classifier can query type sizes and alignments.
30//
31//===----------------------------------------------------------------------===//
32
33#include "PassDetail.h"
35
36#include "mlir/ABI/ABIRewriteContext.h"
37#include "mlir/ABI/ABITypeMapper.h"
38#include "mlir/ABI/Targets/Test/TestTarget.h"
39#include "mlir/Dialect/DLTI/DLTI.h"
40#include "mlir/IR/Builders.h"
41#include "mlir/IR/BuiltinOps.h"
42#include "mlir/IR/SymbolTable.h"
43#include "mlir/Interfaces/DataLayoutInterfaces.h"
44#include "mlir/Pass/Pass.h"
48#include "llvm/ABI/FunctionInfo.h"
49#include "llvm/ABI/TargetInfo.h"
50#include "llvm/ABI/Types.h"
51#include "llvm/ADT/ScopeExit.h"
52#include "llvm/ADT/StringExtras.h"
53#include "llvm/ADT/TypeSwitch.h"
54#include "llvm/IR/CallingConv.h"
55#include "llvm/Support/MathExtras.h"
56
57#include <algorithm>
58#include <array>
59
60using namespace mlir;
61using namespace mlir::abi;
62using namespace cir;
63
64namespace mlir {
65#define GEN_PASS_DEF_CALLCONVLOWERING
66#include "clang/CIR/Dialect/Passes.h.inc"
67} // namespace mlir
68
69namespace {
70
71//===----------------------------------------------------------------------===//
72// x86_64 System V classifier bridge
73//
74// Maps CIR types to llvm::abi::Type, runs the LLVM ABI Lowering Library's SysV
75// x86_64 classifier, and converts the result back into the dialect-agnostic
76// mlir::abi::FunctionClassification that CIRABIRewriteContext consumes.
77// isSupportedType says which CIR types the bridge handles, and a signature
78// naming any other fails the pass instead of being misclassified.
79//===----------------------------------------------------------------------===//
80
81/// Whether a struct's declared argument-passing kind (from the module's
82/// record-layout metadata) allows it to be passed in registers. A record with
83/// no layout entry (e.g. an anonymous struct) has no C++ non-trivial reason to
84/// be forced to memory, so it defaults to can-pass-in-registers.
85static bool recordCanPassInRegs(ModuleOp modOp, cir::RecordType recTy) {
86 auto layout = cir::tryGetRecordLayout(modOp, recTy.getName());
87 if (!layout)
88 return true;
89 return layout.getArgPassingKind() == cir::ArgPassingKind::CanPassInRegs;
90}
91
92/// Whether the classifier could give this type the SSEUP class, looking
93/// through arrays and records at the types they hold.
94static bool mayReachSseUp(mlir::Type ty, const DataLayout &dl) {
95 // The classifier sizes a vector with its width rounded up to a power of two.
96 if (isa<cir::VectorType>(ty))
97 return llvm::PowerOf2Ceil(dl.getTypeSizeInBits(ty).getFixedValue()) >= 128;
98 if (auto fpTy = dyn_cast<cir::FPTypeInterface>(ty))
99 return &fpTy.getFloatSemantics() == &llvm::APFloat::IEEEquad();
100 if (auto arrTy = dyn_cast<cir::ArrayType>(ty))
101 return mayReachSseUp(arrTy.getElementType(), dl);
102 if (auto recTy = dyn_cast<cir::RecordType>(ty))
103 return recTy.isComplete() &&
104 llvm::any_of(recTy.getMembers(),
105 [&](mlir::Type m) { return mayReachSseUp(m, dl); });
106 // The rest classify integer, SSE or memory. A complex is SSE at float and
107 // double width and memory above that, so it needs no walk of its own.
108 assert((isa<cir::IntType, cir::BoolType, cir::PointerType, cir::VPtrType,
109 cir::VoidType, cir::ComplexType, cir::BitFieldType>(ty)) &&
110 "unhandled type in the SSEUP walk");
111 return false;
112}
113
114/// Whether the record's size has no SSEUP coerce. That coerce is a vector as
115/// wide as the record, so only 128, 256 and 512 bits have one. A record past
116/// 512 bits classifies memory before any coerce is asked for.
117static bool sseUpCoerceSizeUnsupported(uint64_t recordBits,
119 const DataLayout &dl) {
120 if (recordBits == 128 || recordBits == 256 || recordBits == 512)
121 return false;
122 if (recordBits < 128 || recordBits > 512)
123 return false;
124 return llvm::any_of(members,
125 [&](mlir::Type m) { return mayReachSseUp(m, dl); });
126}
127
128/// Whether a member is an empty record, looking through arrays, since an array
129/// of empty records supplies no bytes either.
130static bool memberIsEmptyRecord(mlir::Type ty) {
131 while (auto arrTy = dyn_cast<cir::ArrayType>(ty))
132 ty = arrTy.getElementType();
133 auto recTy = dyn_cast<cir::RecordType>(ty);
134 return recTy && recTy.isEmptyForABI();
135}
136
137/// A record's declared alignment, which the ABI uses for the byval and sret
138/// alignment of an indirect argument. DataLayout derives alignment from the
139/// members, so it cannot see `__attribute__((aligned(N)))`. The declared value
140/// comes from the module's record-layout metadata instead. CIRGen emits an
141/// entry for every record it names, so the computed fallback only serves
142/// hand-written CIR.
143static llvm::Align recordDeclaredAlign(ModuleOp modOp, cir::RecordType recTy,
144 const DataLayout &dl) {
145 auto layout = cir::tryGetRecordLayout(modOp, recTy.getName());
146 if (!layout)
147 return llvm::Align(dl.getTypeABIAlignment(recTy));
148 return llvm::Align(layout.getRecordAlign());
149}
150
151/// Whether \p ty, or an aggregate member/element reached by value (never
152/// through a pointer), is an incomplete record. Such a record has no known
153/// layout, so no eightbyte classification can be built for it.
154static bool hasIncompleteRecordByValue(mlir::Type ty) {
155 if (auto recTy = dyn_cast<cir::RecordType>(ty))
156 return !recTy.isComplete() ||
157 llvm::any_of(recTy.getMembers(), hasIncompleteRecordByValue);
158 if (auto arrTy = dyn_cast<cir::ArrayType>(ty))
159 return hasIncompleteRecordByValue(arrTy.getElementType());
160 return false;
161}
162
163/// Whether \p ty has the x87 double extended format, wrapped in LongDoubleType
164/// or not.
165static bool isX87DoubleExtended(mlir::Type ty) {
166 auto fpTy = dyn_cast<cir::FPTypeInterface>(ty);
167 return fpTy &&
168 &fpTy.getFloatSemantics() == &llvm::APFloat::x87DoubleExtended();
169}
170
171/// Whether \p ty is, or holds by value, an x87 double extended value, alone or
172/// as the element of a _Complex or a vector.
173static bool holdsX87DoubleExtended(mlir::Type ty) {
174 if (isa<cir::FPTypeInterface>(ty))
175 return isX87DoubleExtended(ty);
176 if (auto complexTy = dyn_cast<cir::ComplexType>(ty))
177 return isX87DoubleExtended(complexTy.getElementType());
178 if (auto vecTy = dyn_cast<cir::VectorType>(ty))
179 return isX87DoubleExtended(vecTy.getElementType());
180 if (auto arrTy = dyn_cast<cir::ArrayType>(ty))
181 return arrTy.getSize() && holdsX87DoubleExtended(arrTy.getElementType());
182 if (auto recTy = dyn_cast<cir::RecordType>(ty))
183 return llvm::any_of(recTy.getMembers(), holdsX87DoubleExtended);
184 return false;
185}
186
187/// Returns how many bytes from the start of \p ty a value of it reaches. A
188/// scalar reaches the end of its storage, a record the furthest end of its
189/// non-padding members, and an array the end of its last element, so padding
190/// at the end of a record does not count.
191static uint64_t getDataExtentInBytes(mlir::Type ty, const DataLayout &dl) {
192 if (auto recTy = dyn_cast<cir::RecordType>(ty)) {
193 uint64_t extent = 0;
194 for (auto [idx, memberTy, kind] :
195 llvm::enumerate(recTy.getMembers(), recTy.getMemberKinds())) {
196 if (kind == cir::RecordMemberKind::Pad)
197 continue;
198 extent = std::max(extent, recTy.getElementOffset(dl, idx) +
199 getDataExtentInBytes(memberTy, dl));
200 }
201 return extent;
202 }
203 if (auto arrTy = dyn_cast<cir::ArrayType>(ty)) {
204 if (!arrTy.getSize())
205 return 0;
206 mlir::Type elemTy = arrTy.getElementType();
207 return (arrTy.getSize() - 1) * dl.getTypeSize(elemTy).getFixedValue() +
208 getDataExtentInBytes(elemTy, dl);
209 }
210 return dl.getTypeSize(ty).getFixedValue();
211}
212
213/// The CIR types the x86_64 bridge handles. Scalars: an integer up to 128
214/// bits (including `__int128`), a `_BitInt` of any width, pointer, vtable
215/// pointer, bool, void, or any floating-point type. Aggregates: a complete
216/// struct or union whose members are all themselves supported, or an array
217/// of a supported element type. Also a `_Complex`, or a fixed-width vector,
218/// of a supported element type. Everything else is reported NYI at the
219/// reject() choke point in classifyX86_64Function.
220static bool isSupportedType(mlir::Type ty, const DataLayout &dl) {
221 // A pointer is only handled in the default address space (null) or an
222 // already-lowered target address space. A LangAddressSpaceAttr must be
223 // lowered before this pass, so reject it rather than silently dropping it.
224 if (auto ptrTy = dyn_cast<cir::PointerType>(ty))
225 return !ptrTy.getAddrSpace() ||
226 mlir::isa<cir::TargetAddressSpaceAttr>(ptrTy.getAddrSpace());
227 // cir::VPtrType carries no address-space parameter yet, so its target
228 // address space cannot be checked here even though it is not always the
229 // default one.
230 if (isa<cir::VPtrType>(ty)) {
232 return true;
233 }
234 if (isa<cir::VoidType, cir::BoolType>(ty))
235 return true;
236 // Every CIR floating-point type carries the semantics the classifier
237 // switches on, so all of them are handled.
238 if (isa<cir::FPTypeInterface>(ty))
239 return true;
240 if (auto intTy = dyn_cast<cir::IntType>(ty)) {
241 // Integers up to 64 bits, __int128, and _BitInt of any width are
242 // handled: the classifier extends a width below 32, widens 33 through 63
243 // to i64, coerces 65 through 127 to a {i64, i64} pair, and passes 32, 64,
244 // and 128 in the natural type. A _BitInt wider than 128 bits classifies
245 // Indirect, the same path an oversized aggregate already takes.
246 // Non-_BitInt intermediate widths (65..127) do not arise from C and stay
247 // rejected.
248 if (intTy.getIsBitInt())
249 return true;
250 return intTy.getWidth() <= 64 || intTy.getWidth() == 128;
251 }
252 if (auto complexTy = dyn_cast<cir::ComplexType>(ty))
253 return isSupportedType(complexTy.getElementType(), dl);
254 if (auto vecTy = dyn_cast<cir::VectorType>(ty)) {
255 // A scalable vector has no size the SysV eightbyte rules can read, and
256 // x86_64 has no calling convention for one.
257 if (vecTy.getIsScalable())
258 return false;
259 // mapCIRType maps a bool as a one-bit integer, so a bool vector is sized
260 // one bit per element, as clang packs it. Vectors of a _BitInt whose
261 // width is not a whole number of bytes are not handled yet.
262 mlir::Type elemTy = vecTy.getElementType();
263 if (auto elemInt = dyn_cast<cir::IntType>(elemTy)) {
264 if (elemInt.getWidth() % 8)
265 return false;
266 } else if (!isa<cir::FPTypeInterface, cir::BoolType>(elemTy)) {
267 return false;
268 }
269 return isSupportedType(elemTy, dl);
270 }
271 if (auto arrTy = dyn_cast<cir::ArrayType>(ty))
272 return isSupportedType(arrTy.getElementType(), dl);
273 // A bit-field is classified from the type it was declared with and the bits
274 // it holds, and is loaded through its access unit, so both types have to be
275 // ones the bridge handles. A zero-width bit-field has no unit of its own.
276 if (auto bfTy = dyn_cast<cir::BitFieldType>(ty)) {
277 if (mlir::Type storageTy = bfTy.getStorageType())
278 if (!isSupportedType(storageTy, dl))
279 return false;
280 return llvm::all_of(bfTy.getFields(), [&](cir::BitFieldDeclAttr decl) {
281 return isSupportedType(decl.getDeclaredType(), dl);
282 });
283 }
284 if (auto recTy = dyn_cast<cir::RecordType>(ty)) {
285 // An incomplete record has no layout to classify.
286 if (!recTy.isComplete())
287 return false;
288 // The members are checked first so that everything below reasons only
289 // about types the bridge handles.
290 if (!llvm::all_of(recTy.getMembers(),
291 [&](mlir::Type m) { return isSupportedType(m, dl); }))
292 return false;
293 if (recTy.isUnion()) {
294 llvm::ArrayRef<mlir::Type> members = recTy.getMembers();
295 uint64_t recordBits = dl.getTypeSizeInBits(recTy).getFixedValue();
296 // Refuse a union that could reach SSEUP at a size no coerce exists for.
297 // The classifier asserts on those rather than returning a coerce.
298 if (sseUpCoerceSizeUnsupported(recordBits, members, dl))
299 return false;
300 // A member-less union is all padding, which classifies Ignore up to two
301 // eightbytes. Past that SysV says MEMORY regardless of content, and
302 // there is no member here to build the Indirect coercion from.
303 if (members.empty() && recordBits > 128)
304 return false;
305 // A union is moved as a value of its storage type, and an x87 value
306 // stores fewer bytes than it occupies, so the bytes another member
307 // holds past them would be lost. A double extended member stores its
308 // first 10 bytes, so it can share a union with other such members and
309 // with members whose data ends within those bytes, provided it is the
310 // storage type. An x87 value held any other way, in a _Complex, a
311 // vector, a record or an array, is measured at its full storage, which
312 // reaches past them.
313 if (members.size() > 1 && llvm::any_of(members, holdsX87DoubleExtended)) {
314 uint64_t x87StoreBytes = llvm::APFloat::semanticsSizeInBits(
315 llvm::APFloat::x87DoubleExtended()) /
316 8;
317 if (!isX87DoubleExtended(
318 mlir::cast<cir::UnionType>(recTy).getUnionStorageType(dl)) ||
319 !llvm::all_of(members, [&](mlir::Type m) {
320 return isX87DoubleExtended(m) ||
321 getDataExtentInBytes(m, dl) <= x87StoreBytes;
322 }))
323 return false;
324 }
325 // A `_BitInt` access unit past an eightbyte has byte-array storage in
326 // CIR and integer storage in classic CodeGen, so the narrowing walk
327 // finds an i8 in the second eightbyte where classic keeps an i64.
328 if (llvm::any_of(members, [&](mlir::Type m) {
329 auto bfTy = dyn_cast<cir::BitFieldType>(m);
330 if (!bfTy || dl.getTypeSizeInBits(bfTy).getFixedValue() <= 64)
331 return false;
332 return llvm::any_of(bfTy.getFields(), [](cir::BitFieldDeclAttr d) {
333 auto intTy = dyn_cast<cir::IntType>(d.getDeclaredType());
334 return intTy && intTy.getIsBitInt();
335 });
336 }))
337 return false;
338 } else {
339 // A struct's `empty` member that occupies bytes is later read as an
340 // unnamed bit-field. An empty-for-ABI record occupies its own padding,
341 // and reading that as a unit would hand the classifier storage classic
342 // CodeGen ignores. A zero-sized one is dropped before classification,
343 // so a misaligned one never reaches the rule that sends its record to
344 // memory. A union needs neither rule: mapCIRType skips such a variant
345 // instead of reading it as a unit, and every variant sits at offset
346 // zero.
347 for (auto [idx, memberTy, kind] :
348 llvm::enumerate(recTy.getMembers(), recTy.getMemberKinds())) {
349 if (kind != cir::RecordMemberKind::Empty)
350 continue;
351 if (dl.getTypeSizeInBits(memberTy).getFixedValue()) {
352 if (memberIsEmptyRecord(memberTy))
353 return false;
354 } else if (recTy.getElementOffset(dl, idx) %
355 dl.getTypeABIAlignment(memberTy)) {
356 return false;
357 }
358 }
359 }
360 return true;
361 }
362 return false;
363}
364
365/// Convert an llvm::abi::Type coercion type back to a scalar CIR type.
366static mlir::Type abiTypeToCIR(const llvm::abi::Type *ty, MLIRContext *ctx) {
367 if (!ty)
368 return nullptr;
369 return llvm::TypeSwitch<const llvm::abi::Type *, mlir::Type>(ty)
370 .Case(
371 [&](const llvm::abi::VoidType *) { return cir::VoidType::get(ctx); })
372 .Case([&](const llvm::abi::IntegerType *intTy) -> mlir::Type {
373 // mapCIRType maps a bool as a one-bit integer.
374 if (intTy->isBool())
375 return cir::BoolType::get(ctx);
376 return cir::IntType::get(ctx, intTy->getSizeInBits().getFixedValue(),
377 intTy->isSigned(), intTy->isBitInt());
378 })
379 .Case([&](const llvm::abi::FloatType *fltTy) {
380 return cir::getFloatingPointType(*fltTy->getSemantics(), ctx);
381 })
382 .Case([&](const llvm::abi::PointerType *) {
383 return cir::PointerType::get(cir::VoidType::get(ctx));
384 })
385 .Case([&](const llvm::abi::VectorType *vecTy) -> mlir::Type {
386 mlir::Type elemCIR = abiTypeToCIR(vecTy->getElementType(), ctx);
387 if (!elemCIR)
388 return nullptr;
389 return cir::VectorType::get(elemCIR,
390 vecTy->getNumElements().getFixedValue());
391 })
392 .Case([&](const llvm::abi::RecordType *recTy) -> mlir::Type {
393 SmallVector<mlir::Type> fieldTypes;
394 fieldTypes.reserve(recTy->getFields().size());
395 for (const auto &field : recTy->getFields()) {
396 mlir::Type fieldCIR = abiTypeToCIR(field.FieldType, ctx);
397 if (!fieldCIR)
398 return nullptr;
399 fieldTypes.push_back(fieldCIR);
400 }
401 // Coercion types are plain register tuples, not the source record.
402 return cir::StructType::get(
403 ctx, fieldTypes, /*packed=*/false,
404 /*is_class=*/false, cir::RecordType::getAllDataKinds(fieldTypes));
405 })
406 .Default([](const llvm::abi::Type *) -> mlir::Type { return nullptr; });
407}
408
409/// Returns \p ty with a LongDoubleType vector element replaced by its
410/// underlying format, which is the element abiTypeToCIR builds for the same
411/// float.
412static mlir::Type unwrapLongDoubleVectorElement(mlir::Type ty) {
413 if (auto vecTy = dyn_cast<cir::VectorType>(ty)) {
414 if (auto longDoubleTy =
415 dyn_cast<cir::LongDoubleType>(vecTy.getElementType()))
416 return cir::VectorType::get(longDoubleTy.getUnderlying(), vecTy.getSize(),
417 vecTy.getIsScalable());
418 }
419 return ty;
420}
421
422/// Map a CIR type to an llvm::abi::Type. classifyX86_64Function pre-filters
423/// the signature, so only the scalar and struct/array types handled here can
424/// reach this function.
425static const llvm::abi::Type *mapCIRType(mlir::Type type,
426 mlir::abi::ABITypeMapper &typeMapper,
427 const DataLayout &dl, ModuleOp modOp) {
428 llvm::abi::TypeBuilder &tb = typeMapper.getTypeBuilder();
429 return llvm::TypeSwitch<mlir::Type, const llvm::abi::Type *>(type)
430 .Case([&](cir::IntType intTy) {
431 return tb.getIntegerType(intTy.getWidth(),
432 llvm::Align(dl.getTypeABIAlignment(type)),
433 intTy.isSigned(), intTy.getIsBitInt());
434 })
435 .Case([&](cir::PointerType ptrTy) {
436 unsigned addrSpace = 0;
437 if (auto targetAsAttr =
438 dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
439 ptrTy.getAddrSpace()))
440 addrSpace = targetAsAttr.getValue();
441 return tb.getPointerType(dl.getTypeSizeInBits(type),
442 llvm::Align(dl.getTypeABIAlignment(type)),
443 addrSpace);
444 })
445 .Case([&](cir::VPtrType) {
446 // cir::VPtrType carries no address-space parameter yet, so this
447 // always maps into the default one until that gap closes.
449 return tb.getPointerType(dl.getTypeSizeInBits(type),
450 llvm::Align(dl.getTypeABIAlignment(type)));
451 })
452 .Case([&](cir::BoolType) {
453 // A bool is a one-bit integer to the classifier, as QualTypeMapper
454 // maps it, so a bool vector is sized one bit per element.
455 return tb.getIntegerType(1, llvm::Align(dl.getTypeABIAlignment(type)),
456 /*Signed=*/false);
457 })
458 .Case([&](cir::VoidType) { return tb.getVoidType(); })
459 .Case([&](cir::FPTypeInterface fpTy) {
460 // LongDoubleType reports its underlying format's semantics, so the
461 // classifier sees x87 or IEEE quad rather than the wrapper.
462 return tb.getFloatType(fpTy.getFloatSemantics(),
463 llvm::Align(dl.getTypeABIAlignment(type)));
464 })
465 .Case([&](cir::ComplexType complexTy) {
466 return tb.getComplexType(
467 mapCIRType(complexTy.getElementType(), typeMapper, dl, modOp),
468 llvm::Align(dl.getTypeABIAlignment(type)));
469 })
470 .Case([&](cir::VectorType vecTy) {
471 // isSupportedType rejects a scalable vector, so the element count is
472 // always fixed here.
473 return tb.getVectorType(
474 mapCIRType(vecTy.getElementType(), typeMapper, dl, modOp),
475 llvm::ElementCount::getFixed(vecTy.getSize()),
476 llvm::Align(dl.getTypeABIAlignment(type)));
477 })
478 .Case([&](cir::ArrayType arrTy) {
479 const llvm::abi::Type *elemAbi =
480 mapCIRType(arrTy.getElementType(), typeMapper, dl, modOp);
481 return tb.getArrayType(elemAbi, arrTy.getSize(),
482 dl.getTypeSizeInBits(type).getFixedValue());
483 })
484 .Case([&](cir::RecordType recTy) -> const llvm::abi::Type * {
485 llvm::abi::RecordFlags flags = llvm::abi::RecordFlags::None;
486 if (recordCanPassInRegs(modOp, recTy))
487 flags = flags | llvm::abi::RecordFlags::CanPassInRegisters;
488 llvm::TypeSize sizeBits = llvm::TypeSize::getFixed(
489 dl.getTypeSizeInBits(type).getFixedValue());
490 llvm::Align align = recordDeclaredAlign(modOp, recTy, dl);
491
492 // Mapped with no fields, an empty record reaches Ignore on its own.
493 // The size still matters: past two eightbytes SysV says memory whatever
494 // the content.
495 // TODO: AArch64 needs the unadjusted alignment. We'll need to add that
496 // to RecordLayoutAttr.
497 if (recTy.isEmptyForABI())
498 return tb.getRecordType(
499 /*Fields=*/{}, sizeBits, align, /*UnadjustedAlign=*/align,
500 llvm::abi::StructPacking::Default,
501 /*BaseClasses=*/{}, /*VirtualBaseClasses=*/{}, flags);
502
504 fields.reserve(recTy.getMembers().size());
505
506 // The classifier reads one entry per source bit-field, so a unit is
507 // spread back out into the fields it holds. x86_64 is little-endian,
508 // so the unit's first byte holds the first of them, and the rest
509 // follow at the widths ahead of them.
510 //
511 // A coercion for an eightbyte is built from the type at that
512 // eightbyte's first byte, where the unit's first field sits, so that
513 // field's entry carries the unit rather than its own declared type.
514 // The bits holding user data are a separate question, and the answer
515 // is the extent of the type each field was declared with, which the
516 // eightbyte rules read through to decide whether a narrower coercion
517 // would drop something. One entry cannot answer both, so a unit
518 // narrower than its first field's declaration takes an extra entry for
519 // that declaration, holding no bits of its own. A zero-width
520 // bit-field has no unit and so contributes only the declaration.
521 //
522 // A width of zero is how the classifier recognizes the entries that
523 // take no part in assigning eightbyte classes, so the width goes
524 // through as declared.
525 auto addAccessUnit = [&](cir::BitFieldType bfTy,
526 uint64_t unitOffsetBits) {
527 mlir::Type unitTy = bfTy.getStorageType();
528 uint64_t unitBits =
529 unitTy ? dl.getTypeSizeInBits(unitTy).getFixedValue() : 0;
530 for (auto [idx, decl] : llvm::enumerate(bfTy.getFields())) {
531 const uint64_t offsetBits =
532 unitOffsetBits + bfTy.getFieldBitOffset(idx);
533 const bool holdsUnit = idx == 0 && unitTy;
534 if (holdsUnit)
535 fields.push_back(llvm::abi::FieldInfo(
536 mapCIRType(unitTy, typeMapper, dl, modOp), offsetBits,
537 /*IsBitField=*/true, decl.getWidth(),
538 /*IsUnnamedBitField=*/decl.getIsUnnamed()));
539 mlir::Type declaredTy = decl.getDeclaredType();
540 if (!holdsUnit ||
541 dl.getTypeSizeInBits(declaredTy).getFixedValue() > unitBits)
542 fields.push_back(llvm::abi::FieldInfo(
543 mapCIRType(declaredTy, typeMapper, dl, modOp), offsetBits,
544 /*IsBitField=*/true, holdsUnit ? 0 : decl.getWidth(),
545 /*IsUnnamedBitField=*/holdsUnit || decl.getIsUnnamed()));
546 }
547 };
548
549 // The size passed here spans the tail padding, so an eightbyte covers
550 // the whole union rather than just the member the classifier reduces
551 // it to.
552 if (recTy.isUnion()) {
553 // Classify only the variants that supply data, judged by each
554 // variant's own storage rather than by its mark. One supplying
555 // none is skipped so it does not appear as a spurious argument.
556 // Whether the record is empty at all is settled from the marks
557 // before this. Every variant starts at offset zero, so a
558 // bit-field variant needs no offset of its own.
559 assert(!llvm::is_contained(recTy.getMemberKinds(),
560 cir::RecordMemberKind::Pad) &&
561 "a union member cannot be marked pad");
562 for (mlir::Type variantTy : recTy.getMembers()) {
563 if (auto bfTy = dyn_cast<cir::BitFieldType>(variantTy)) {
564 // A variant that is an unnamed bit-field holds data all the
565 // same, so it is flagged rather than skipped, as in the struct
566 // path below.
567 addAccessUnit(bfTy, /*unitOffsetBits=*/0);
568 continue;
569 }
570 if (dl.getTypeSizeInBits(variantTy).getFixedValue() == 0 ||
571 memberIsEmptyRecord(variantTy))
572 continue;
573 fields.push_back(llvm::abi::FieldInfo(
574 mapCIRType(variantTy, typeMapper, dl, modOp)));
575 }
576 return tb.getUnionType(fields, sizeBits, align,
577 /*UnadjustedAlign=*/align,
578 llvm::abi::StructPacking::Default, flags);
579 }
580
581 // Padding is dropped, so the eightbyte rules see its bytes as holding
582 // nothing, while the record's full size set above still spans them. An
583 // unnamed bit-field is flagged rather than dropped, since classic
584 // CodeGen ignores it when assigning eightbyte classes but counts it
585 // when choosing the coerce type, and a member's presence alone cannot
586 // say both.
587 for (auto [idx, fieldTy, kind] :
588 llvm::enumerate(recTy.getMembers(), recTy.getMemberKinds())) {
589 if (kind == cir::RecordMemberKind::Pad)
590 continue;
591 if (auto bfTy = dyn_cast<cir::BitFieldType>(fieldTy)) {
592 addAccessUnit(bfTy, recTy.getElementOffset(dl, idx) * 8);
593 continue;
594 }
595 // An `empty` member that is not a bit-field still stands for bytes
596 // no field of the source reads, so it is flagged the same way.
597 bool isUnnamed = kind == cir::RecordMemberKind::Empty;
598 uint64_t widthBits = dl.getTypeSizeInBits(fieldTy).getFixedValue();
599 if (isUnnamed && widthBits == 0)
600 continue;
601 assert((!isUnnamed || !memberIsEmptyRecord(fieldTy)) &&
602 "an empty-for-ABI member must not reach the classifier as an "
603 "unnamed bit-field");
604 fields.push_back(llvm::abi::FieldInfo(
605 mapCIRType(fieldTy, typeMapper, dl, modOp),
606 recTy.getElementOffset(dl, idx) * 8,
607 /*IsBitField=*/isUnnamed, isUnnamed ? widthBits : 0,
608 /*IsUnnamedBitField=*/isUnnamed));
609 }
610
611 return tb.getRecordType(
612 fields, sizeBits, align, /*UnadjustedAlign=*/align,
613 llvm::abi::StructPacking::Default,
614 /*BaseClasses=*/{}, /*VirtualBaseClasses=*/{}, flags);
615 })
616 .Default([](mlir::Type) -> const llvm::abi::Type * {
617 llvm_unreachable(
618 "mapCIRType: type not pre-filtered by classifyX86_64Function");
619 });
620}
621
622/// Convert an llvm::abi::ArgInfo into the ArgClassification consumed by
623/// CIRABIRewriteContext.
624///
625/// Direct: the value passes in register(s). A coercion is forwarded in the
626/// four cases where the value has to be rebuilt on the wire: an aggregate
627/// unpacked into the register(s) holding it, a scalar too wide for one register
628/// split into a tuple of them, a scalar the classifier widens to fill its
629/// eightbyte, and a value whose live bytes start partway into its storage
630/// because a leading eightbyte holds no field (getDirectOffset). canFlatten
631/// follows the classifier's CanBeFlattened, so the rewriter splits a
632/// multi-field coerced struct into individual wire arguments unless the
633/// classifier asked to keep it intact. Any other scalar passes in its
634/// natural CIR type, which a null coercion denotes. A coercion this bridge
635/// cannot represent yields std::nullopt so the caller reports NYI rather than
636/// silently passing the value unchanged.
637///
638/// Extend: bool or a sub-register integer needs a signext/zeroext attribute.
639/// The x86_64 classifier (llvm/lib/ABI/Targets/X86.cpp) only returns Extend
640/// for an integer or bool operand, so any other origTy is asserted rather
641/// than silently handled.
642///
643/// Indirect: an aggregate that does not fit in registers, or a scalar too
644/// wide to fit (a `_BitInt` over 128 bits), is passed via a pointer (sret
645/// for returns, byval for arguments).
646///
647/// Ignore: a void return, or an empty record dropped from the signature.
648static std::optional<ArgClassification>
649convertABIArgInfo(const llvm::abi::ArgInfo &info, MLIRContext *ctx,
650 mlir::Type origTy) {
651 if (info.isDirect()) {
652 unsigned offset = info.getDirectOffset();
653 // The classifier names a coerce type even where it matches the natural
654 // type, so a non-null coerce does not by itself mean a rewrite is needed.
655 const llvm::abi::Type *coerceAbi = info.getCoerceToType();
656 bool isAggregate = isa_and_present<cir::RecordType, cir::ArrayType>(origTy);
657 // For a _Complex or a vector the classifier's coerce is only sometimes the
658 // natural type, so it has to be read rather than assumed.
659 bool comparesAgainstCoerce =
660 coerceAbi && isa_and_present<cir::ComplexType, cir::VectorType>(origTy);
661 bool coerceIsRegisterTuple =
662 isa_and_present<llvm::abi::RecordType>(coerceAbi);
663 // A tuple coercion cannot be read at an offset, so refuse the pair rather
664 // than emit a read of the wrong bytes.
665 if (offset && coerceIsRegisterTuple)
666 return std::nullopt;
667 // Compare widths rather than identity: a coerce no wider than the natural
668 // type carries the same value and needs no rewrite.
669 auto origInt = dyn_cast_if_present<cir::IntType>(origTy);
670 const auto *coerceInt =
671 dyn_cast_if_present<llvm::abi::IntegerType>(coerceAbi);
672 bool coerceWidensScalar =
673 origInt && coerceInt &&
674 coerceInt->getSizeInBits().getFixedValue() > origInt.getWidth();
675 // Leaving the rest alone also avoids a lossy round trip: abiTypeToCIR
676 // drops the LongDoubleType wrapper and a pointer's pointee, so comparing a
677 // scalar against its own coerce would report a difference that is not
678 // one. Passing a value through reads it from byte 0, so one living at
679 // an offset cannot take this path.
680 if (!offset && !isAggregate && !comparesAgainstCoerce &&
681 !coerceIsRegisterTuple && !coerceWidensScalar)
682 return ArgClassification::getDirect();
683 mlir::Type coerced = abiTypeToCIR(coerceAbi, ctx);
684 if (!coerced)
685 return std::nullopt;
686 bool coerceIsNatural = coerced == unwrapLongDoubleVectorElement(origTy);
687 // An offset would be lost here, since a coercion to the value's own type
688 // is indistinguishable from no coercion at all.
689 if (offset && coerceIsNatural)
690 return std::nullopt;
691 // Coercing a value to the type it already has would add a memory round
692 // trip for nothing.
693 if (comparesAgainstCoerce && coerceIsNatural)
694 return ArgClassification::getDirect();
695 ArgClassification classified =
696 ArgClassification::getDirect(coerced, offset);
697 classified.canFlatten = info.getCanBeFlattened();
698 return classified;
699 }
700 // An extended value is always read from byte 0 of its own storage, so
701 // there is no offset to honor here.
702 if (info.isExtend()) {
703 if (isa_and_present<cir::BoolType>(origTy))
704 return ArgClassification::getExtend(nullptr, info.isSignExt());
705 assert((!origTy || isa<cir::IntType>(origTy)) &&
706 "the x86_64 classifier only returns Extend for integers and bool");
707 mlir::Type extendedTy = abiTypeToCIR(info.getCoerceToType(), ctx);
708 return ArgClassification::getExtend(extendedTy, info.isSignExt());
709 }
710 if (info.isIndirect())
711 return ArgClassification::getIndirect(info.getIndirectAlign(),
712 info.getIndirectByVal());
713 // AArch64 pure scalable aggregates use CoerceAndExpand. This bridge lowers
714 // x86_64 classifications only.
715 assert(!info.isCoerceAndExpand() &&
716 "CoerceAndExpand is not expected for x86_64");
717 assert(info.isIgnore() && "Unexpected classification");
718 return ArgClassification::getIgnore();
719}
720
721/// Where \p fnTy's declared parameters end and its ellipsis arguments begin.
722///
723/// The only x86_64 rule that reads this boundary sends an unnamed vector wider
724/// than 128 bits to memory.
725static llvm::abi::RequiredArgs requiredArgs(cir::FuncType fnTy) {
726 if (!fnTy.isVarArg())
727 return llvm::abi::RequiredArgs::All;
728 return llvm::abi::RequiredArgs(fnTy.getNumInputs());
729}
730
731/// Classify an x86_64 SysV signature (return type + argument types) using the
732/// LLVM ABI library. Shared by the cir.func path, the variadic-call path and
733/// the indirect-call path (the latter classifies from the callee function
734/// pointer's pointee FuncType). \p required marks where the declared
735/// parameters in \p inputs end. The classifier treats every argument past that
736/// point as passed through an ellipsis. Returns std::nullopt and emits an NYI
737/// error via \p emitError if the signature uses a type the bridge does not
738/// handle yet.
739static std::optional<FunctionClassification> classifyX86_64Signature(
740 mlir::Type retCIR, mlir::TypeRange inputs, llvm::abi::RequiredArgs required,
741 MLIRContext *ctx, const DataLayout &dl,
742 mlir::abi::ABITypeMapper &typeMapper,
743 const llvm::abi::TargetInfo &targetInfo, ModuleOp modOp,
744 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) {
745 assert(retCIR && "signature return type must be non-null");
746 assert((!required.allowsOptionalArgs() ||
747 required.getNumRequiredArgs() <= inputs.size()) &&
748 "declared parameters cannot outnumber the classified arguments");
749 bool voidRet = isa<cir::VoidType>(retCIR);
750
751 auto reject = [&](mlir::Type t) -> bool {
752 if (isSupportedType(t, dl))
753 return false;
754 emitError()
755 << "x86_64 calling-convention lowering not yet implemented for type "
756 << t;
757 return true;
758 };
759 if (!voidRet && reject(retCIR))
760 return std::nullopt;
761 for (mlir::Type a : inputs)
762 if (reject(a))
763 return std::nullopt;
764
765 const llvm::abi::Type *retAbi =
766 voidRet ? typeMapper.getTypeBuilder().getVoidType()
767 : mapCIRType(retCIR, typeMapper, dl, modOp);
769 for (mlir::Type a : inputs)
770 argAbi.push_back(mapCIRType(a, typeMapper, dl, modOp));
771
772 std::unique_ptr<llvm::abi::FunctionInfo> fi = llvm::abi::FunctionInfo::create(
773 llvm::CallingConv::C, retAbi, argAbi, required);
774 targetInfo.computeInfo(*fi);
775
776 // convertABIArgInfo returns nullopt when the classifier picks a coercion this
777 // bridge cannot represent.
778 auto nyiCoercion = [&](mlir::Type t) {
779 emitError() << "x86_64 calling-convention lowering not yet "
780 "implemented for the ABI coercion of type "
781 << t;
782 };
783
784 FunctionClassification fc;
785 fc.returnsVoid = voidRet;
786 mlir::Type origRet = voidRet ? mlir::Type() : retCIR;
787 std::optional<ArgClassification> retAc =
788 convertABIArgInfo(fi->getReturnInfo(), ctx, origRet);
789 if (!retAc) {
790 nyiCoercion(retCIR);
791 return std::nullopt;
792 }
793 fc.returnInfo = *retAc;
794 for (unsigned i = 0, e = fi->arg_size(); i < e; ++i) {
795 mlir::Type origArg = i < inputs.size() ? inputs[i] : mlir::Type();
796 const llvm::abi::ArgInfo &argInfo = fi->getArgInfo(i).Info;
797 std::optional<ArgClassification> ac =
798 convertABIArgInfo(argInfo, ctx, origArg);
799 if (!ac) {
800 nyiCoercion(origArg);
801 return std::nullopt;
802 }
803 ac->neededIntRegs = argInfo.getNeededIntRegs();
804 ac->neededSseRegs = argInfo.getNeededSseRegs();
805 fc.argInfos.push_back(*ac);
806 }
807 return fc;
808}
809
810/// The AVX level to classify \p func at: \p base, raised if the function's own
811/// recorded feature list enables a wider vector.
812static llvm::abi::X86AVXABILevel funcAvxLevel(cir::FuncOp func,
813 llvm::abi::X86AVXABILevel base) {
814 // Only a `target` attribute may raise the level. A multiversioned function
815 // carries a raised feature list too, and must stay at the module's level.
817
818 auto features = func->getAttrOfType<mlir::StringAttr>("cir.target-features");
819 if (!features)
820 return base;
821 // A '-' entry disables the feature, so match a whole '+' entry rather than
822 // searching for the name. avx512f implies avx, so both entries are present:
823 // return on the wider name so one pass suffices.
824 bool avx = false;
825 for (llvm::StringRef feature : llvm::split(features.getValue(), ',')) {
826 if (!feature.consume_front("+"))
827 continue;
828 if (feature == "avx512f")
829 return std::max(base, llvm::abi::X86AVXABILevel::AVX512);
830 avx |= feature == "avx";
831 }
832 return avx ? std::max(base, llvm::abi::X86AVXABILevel::AVX) : base;
833}
834
835/// Classify a cir.func for x86_64 SysV using the LLVM ABI library. Returns
836/// std::nullopt and emits an NYI error if the signature uses a type the bridge
837/// does not handle yet.
838static std::optional<FunctionClassification>
839classifyX86_64Function(cir::FuncOp func, const DataLayout &dl,
840 mlir::abi::ABITypeMapper &typeMapper,
841 const llvm::abi::TargetInfo &targetInfo,
842 ModuleOp modOp) {
843 cir::FuncType fnTy = func.getFunctionType();
844 return classifyX86_64Signature(fnTy.getReturnType(), fnTy.getInputs(),
845 requiredArgs(fnTy), func->getContext(), dl,
846 typeMapper, targetInfo, modOp,
847 [&]() { return func.emitOpError(); });
848}
849
850/// Classify the single type fetched by a `cir.va_arg` as an unnamed argument
851/// (RequiredArgs(0)) with a full register budget. Returns std::nullopt and
852/// emits an NYI error if the type is not one this bridge handles.
853static std::optional<ArgClassification> classifyX86_64VarArgType(
854 mlir::Type ty, MLIRContext *ctx, const DataLayout &dl,
855 mlir::abi::ABITypeMapper &typeMapper,
856 const llvm::abi::TargetInfo &targetInfo, ModuleOp modOp,
857 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) {
858 std::optional<FunctionClassification> fc = classifyX86_64Signature(
859 cir::VoidType::get(ctx), mlir::TypeRange(ty), llvm::abi::RequiredArgs(0),
860 ctx, dl, typeMapper, targetInfo, modOp, emitError);
861 if (!fc)
862 return std::nullopt;
863 return fc->argInfos[0];
864}
865
866/// Classify a call that passes arguments through an ellipsis. The callee's
867/// own classification covers only its declared parameters, but an ellipsis
868/// argument competes for the same argument registers as a declared one, so
869/// what the ABI does with it depends on the whole argument list: the same
870/// small struct is passed in registers early in the list and in memory once
871/// the integer registers are gone. Classifying from the call's operands
872/// rather than the callee's signature is what makes that accounting right.
873static std::optional<FunctionClassification> classifyX86_64VariadicCall(
874 cir::CIRCallOpInterface call, cir::FuncType calleeTy, const DataLayout &dl,
875 mlir::abi::ABITypeMapper &typeMapper,
876 const llvm::abi::TargetInfo &targetInfo, ModuleOp modOp) {
877 assert(calleeTy.isVarArg() &&
878 "only a variadic callee can take more operands than it declares");
879 Operation *op = call.getOperation();
880 return classifyX86_64Signature(
881 calleeTy.getReturnType(), call.getArgOperands().getTypes(),
882 requiredArgs(calleeTy), op->getContext(), dl, typeMapper, targetInfo,
883 modOp, [&]() { return op->emitOpError(); });
884}
885
886/// Whether \p fc gives the callee access to memory through a pointer the ABI
887/// introduced: an sret slot for an indirect return, or an indirect argument.
888static bool hasIndirectSlot(const FunctionClassification &fc) {
889 if (fc.returnInfo.kind == ArgKind::Indirect)
890 return true;
891 return llvm::any_of(fc.argInfos, [](const ArgClassification &ac) {
892 return ac.kind == ArgKind::Indirect;
893 });
894}
895
896/// Record on \p op that the memory its pointer arguments address may be read
897/// and written. Absent effects already allow that, since an absent attribute
898/// means the effects are unknown, so they are left absent.
899template <typename OpTy> static void widenForArgMemory(OpTy op) {
900 cir::MemoryEffectsAttr effects = op.getMemoryEffectsAttr();
901 if (!effects)
902 return;
903 op.setMemoryEffectsAttr(cir::MemoryEffectsAttr::get(
904 effects.getContext(), effects.getOther(), cir::ModRefInfo::ModRef,
905 effects.getInaccessibleMem(), effects.getErrnoMem(),
906 effects.getTargetMem0(), effects.getTargetMem1()));
907}
908
909#ifndef NDEBUG
910/// Whether \p callFc classifies a call's leading arguments and its return
911/// exactly as \p calleeFc classifies the callee's declared parameters and
912/// return. A function definition and its call sites are rewritten from
913/// separate classifications, so the two would silently disagree on the wire
914/// format if an ellipsis argument could ever change how a declared parameter
915/// is passed.
916static bool classifiesSamePrefix(const FunctionClassification &calleeFc,
917 const FunctionClassification &callFc) {
918 if (callFc.argInfos.size() < calleeFc.argInfos.size())
919 return false;
920 return calleeFc.returnInfo == callFc.returnInfo &&
921 std::equal(calleeFc.argInfos.begin(), calleeFc.argInfos.end(),
922 callFc.argInfos.begin());
923}
924#endif
925
926struct CallConvLoweringPass
927 : public impl::CallConvLoweringBase<CallConvLoweringPass> {
928 using CallConvLoweringBase::CallConvLoweringBase;
929
930 CallConvLoweringPass(const CallConvLoweringOptions &options,
931 const llvm::abi::X86ABICompatInfo &x86AbiCompat)
932 : CallConvLoweringBase(options), x86AbiCompat(x86AbiCompat) {}
933
934 void runOnOperation() override;
935
936 /// The x86_64 flags whose value depends on the target and the requested ABI
937 /// compatibility version. Carried outside the pass options because the
938 /// struct has no command-line parser, so a cir-opt run gets the library
939 /// defaults rather than a target's values.
940 llvm::abi::X86ABICompatInfo x86AbiCompat;
941};
942
943/// Record on \p fc whether \p returnType is CIR's void. The x86_64 classifier
944/// answers this itself, but the other two drivers cannot: the test target is
945/// dialect-neutral and has no notion of CIR's void, and the
946/// classification-attr schema carries no return type at all. Both route
947/// through here so a classification always reaches needsRewrite paired with
948/// the return type it was built from.
949static std::optional<FunctionClassification>
950withReturnVoidness(std::optional<FunctionClassification> fc,
951 mlir::Type returnType) {
952 if (fc)
953 fc->returnsVoid = mlir::isa<cir::VoidType>(returnType);
954 return fc;
955}
956
957/// Classify \p func using whichever driver mode is configured. Returns
958/// std::nullopt and emits an error on the function if classification fails
959/// (e.g. injection-driver mode but the function is missing the attribute,
960/// or the attribute is malformed).
961std::optional<FunctionClassification>
962classifyFunction(cir::FuncOp func, const DataLayout &dl,
963 cir::CallConvTarget target, StringRef classificationAttrName) {
964 ArrayRef<Type> argTypes = func.getFunctionType().getInputs();
965 Type returnType = func.getFunctionType().getReturnType();
966
967 if (!classificationAttrName.empty()) {
968 auto attr = func->getAttrOfType<DictionaryAttr>(classificationAttrName);
969 if (!attr) {
970 func.emitOpError()
971 << "missing classification attribute '" << classificationAttrName
972 << "' (CallConvLowering driver mode 'classification-attr')";
973 return std::nullopt;
974 }
975 return withReturnVoidness(mlir::abi::test::parseClassificationAttr(
976 attr, [&]() { return func.emitOpError(); }),
977 returnType);
978 }
979
980 // The x86_64 target is handled directly in runOnOperation (it needs a shared
981 // ABITypeMapper and TargetInfo), so only the test target reaches here.
982 assert(target == cir::CallConvTarget::Test &&
983 "classifyFunction only handles the test target");
984 return withReturnVoidness(mlir::abi::test::classify(argTypes, returnType, dl),
985 returnType);
986}
987
988/// Find the cir.func declaration matching a direct cir.call / cir.try_call
989/// callee, if any. Returns nullptr if the callee is indirect or the symbol
990/// cannot be resolved. Takes a SymbolTable instead of a ModuleOp so the
991/// symbol lookup is amortized across all the call sites the driver walks
992/// (ModuleOp::lookupSymbol is linear per call).
993cir::FuncOp lookupCallee(Operation *callOp, SymbolTable &symbolTable) {
994 FlatSymbolRefAttr callee;
995 if (auto call = dyn_cast<cir::CallOp>(callOp))
996 callee = call.getCalleeAttr();
997 else if (auto tryCall = dyn_cast<cir::TryCallOp>(callOp))
998 callee = tryCall.getCalleeAttr();
999 else
1000 return nullptr;
1001 if (!callee)
1002 return nullptr;
1003 return symbolTable.lookup<cir::FuncOp>(callee.getValue());
1004}
1005
1006void CallConvLoweringPass::runOnOperation() {
1007 ModuleOp moduleOp = getOperation();
1008 MLIRContext *ctx = &getContext();
1009
1010 bool haveTarget = target != cir::CallConvTarget::None;
1011 bool haveAttr = !classificationAttr.empty();
1012 if (haveTarget == haveAttr) {
1013 moduleOp.emitOpError() << "CallConvLowering requires exactly one of "
1014 "'target' or 'classification-attr' pass options";
1015 signalPassFailure();
1016 return;
1017 }
1018
1019 if (!moduleOp->hasAttr(DLTIDialect::kDataLayoutAttrName)) {
1020 moduleOp.emitOpError()
1021 << "CallConvLowering requires a DataLayout (dlti.dl_spec attribute "
1022 "on the module)";
1023 signalPassFailure();
1024 return;
1025 }
1026
1027 DataLayout dl(moduleOp);
1028 CIRABIRewriteContext rewriteCtx(moduleOp, dl);
1029 // A non-byval indirect parameter's slot outlives the rewrite that retypes
1030 // the parameter, so that a call forwarding the parameter can still recognize
1031 // it. Draining on scope exit collapses those slots whichever way this
1032 // function returns.
1033 llvm::scope_exit drainParamSlots(
1034 [&] { rewriteCtx.finalizeParameterSlots(); });
1035 SymbolTable symbolTable(moduleOp);
1036
1037 // A per-function target attribute can raise the AVX level, so one classifier
1038 // per module would misclassify a wide vector in such a function.
1039 static constexpr unsigned numAvxLevels =
1040 static_cast<unsigned>(llvm::abi::X86AVXABILevel::Last) + 1;
1041 bool isX86 = target == cir::CallConvTarget::X86_64;
1042 std::optional<mlir::abi::ABITypeMapper> x86TypeMapper;
1043 std::array<std::unique_ptr<llvm::abi::TargetInfo>, numAvxLevels> x86Targets;
1044 if (isX86)
1045 x86TypeMapper.emplace(dl);
1046 auto x86TargetFor =
1047 [&](llvm::abi::X86AVXABILevel level) -> const llvm::abi::TargetInfo & {
1048 assert(static_cast<unsigned>(level) < numAvxLevels &&
1049 "a new X86AVXABILevel must move X86AVXABILevel::Last");
1050 std::unique_ptr<llvm::abi::TargetInfo> &slot =
1051 x86Targets[static_cast<unsigned>(level)];
1052 if (!slot)
1053 slot = llvm::abi::createX86_64TargetInfo(
1054 x86TypeMapper->getTypeBuilder(), level,
1055 /*Has64BitPointers=*/true, x86AbiCompat);
1056 return *slot;
1057 };
1058 llvm::abi::X86AVXABILevel baseAvxLevel = x86AvxAbiLevel.getValue();
1059 auto avxLevelFor = [&](cir::FuncOp func) -> llvm::abi::X86AVXABILevel {
1060 if (!allowsX86TargetAttrAvx || !func)
1061 return baseAvxLevel;
1062 return funcAvxLevel(func, baseAvxLevel);
1063 };
1064
1065 // Classify every cir.func up front. No IR mutation happens here, so
1066 // later walks can consult any function's classification regardless of
1067 // visitation order.
1068 llvm::MapVector<cir::FuncOp, FunctionClassification> classifications;
1069 bool anyFailed = false;
1070 moduleOp.walk([&](cir::FuncOp f) {
1071 // A complete type is required at any call or definition, so only a
1072 // declaration can carry an incomplete-by-value parameter or return type,
1073 // and no translation unit can ever call or define it with real argument
1074 // data. Leave it unclassified.
1075 cir::FuncType fnTy = f.getFunctionType();
1076 if (f.isDeclaration() &&
1077 (hasIncompleteRecordByValue(fnTy.getReturnType()) ||
1078 llvm::any_of(fnTy.getInputs(), hasIncompleteRecordByValue)))
1079 return;
1080 std::optional<FunctionClassification> fc;
1081 if (isX86)
1082 fc = classifyX86_64Function(f, dl, *x86TypeMapper,
1083 x86TargetFor(avxLevelFor(f)), moduleOp);
1084 else
1085 fc = classifyFunction(f, dl, target, classificationAttr);
1086 if (!fc) {
1087 anyFailed = true;
1088 return;
1089 }
1090 classifications.insert({f, std::move(*fc)});
1091 });
1092 if (anyFailed) {
1093 signalPassFailure();
1094 return;
1095 }
1096
1097 // Build a callee-to-callers index. One module walk collects every direct
1098 // cir.call / cir.try_call to each cir.func; the loop below rewrites a
1099 // function and all of its call sites together. Indirect or unresolved
1100 // callees are skipped here; rewriteCallSite errors on those at the end.
1101 //
1102 // A call that passes arguments through an ellipsis gets its own
1103 // classification, recorded here while every signature is still in its
1104 // original form. The callee's classification covers only its declared
1105 // parameters and cannot describe those extra arguments.
1106 llvm::DenseMap<cir::FuncOp, SmallVector<Operation *>> callers;
1107 // Keyed on the call op collected below, looked up once when that same op is
1108 // rewritten. A key must never come from an op created during the rewrite:
1109 // a recycled address could match an unrelated entry.
1110 llvm::DenseMap<Operation *, FunctionClassification> variadicCallSites;
1111 moduleOp.walk([&](Operation *op) {
1112 auto call = dyn_cast<cir::CIRCallOpInterface>(op);
1113 if (!call)
1114 return;
1115 cir::FuncOp callee = lookupCallee(op, symbolTable);
1116 if (!callee)
1117 return;
1118 callers[callee].push_back(op);
1119
1120 // Only the x86_64 driver classifies per call site. Under the other
1121 // drivers the classification comes from a fixed per-function source, so
1122 // such a call stays short a classification and rewriteCallSite reports it.
1123 cir::FuncType calleeTy = callee.getFunctionType();
1124 if (!isX86 || call.getNumArgOperands() <= calleeTy.getNumInputs())
1125 return;
1126 // A callee declared without a prototype also takes more operands than it
1127 // declares, and the verifier allows it. Those extra arguments are named
1128 // rather than passed through an ellipsis, so the accounting below does not
1129 // describe them.
1130 if (!calleeTy.isVarArg()) {
1131 op->emitOpError() << "extra arguments to a callee without a prototype "
1132 "not yet implemented in CallConvLowering";
1133 anyFailed = true;
1134 return;
1135 }
1136 // The callee's level, not the caller's: this pass rewrites the definition
1137 // and its call sites from one classification, so they have to agree.
1138 // Classic instead arranges every call site from the caller and reports a
1139 // caller whose level disagrees with its callee in checkFunctionCallABI,
1140 // which has no equivalent here yet.
1141 std::optional<FunctionClassification> fc =
1142 classifyX86_64VariadicCall(call, calleeTy, dl, *x86TypeMapper,
1143 x86TargetFor(avxLevelFor(callee)), moduleOp);
1144 if (!fc) {
1145 anyFailed = true;
1146 return;
1147 }
1148 variadicCallSites.insert({op, std::move(*fc)});
1149 });
1150 if (anyFailed) {
1151 signalPassFailure();
1152 return;
1153 }
1154
1155 // A cir.get_global holding a function's address carries the signature the
1156 // source wrote, which the verifier ties to the callee, so it goes stale when
1157 // that callee is rewritten. A function address in a global initializer is a
1158 // GlobalViewAttr instead, whose recorded type the verifier does not tie to
1159 // the callee and which is dropped at opaque-pointer lowering, so it needs no
1160 // counterpart.
1161 llvm::DenseMap<cir::FuncOp, SmallVector<cir::GetGlobalOp>> addressTakers;
1162 moduleOp.walk([&](cir::GetGlobalOp getGlobal) {
1163 auto ptrTy = cast<cir::PointerType>(getGlobal.getAddr().getType());
1164 if (!isa<cir::FuncType>(ptrTy.getPointee()))
1165 return;
1166 // A get_global's pointee must equal the named symbol's type, and the
1167 // GlobalOp verifier rejects a function type there, so this names a
1168 // cir.func.
1169 auto callee = cast<cir::FuncOp>(symbolTable.lookup(getGlobal.getName()));
1170 addressTakers[callee].push_back(getGlobal);
1171 });
1172
1173 // Restate every non-byval indirect parameter's slot alignment and route any
1174 // use of such a parameter as a call argument through a load of that slot,
1175 // before any definition or call site is rewritten. Doing this up front
1176 // makes the forwarding decision independent of the order the callee and its
1177 // caller were declared in.
1178 for (auto &kv : classifications) {
1179 if (failed(rewriteCtx.prepareNonByvalParameters(kv.first, kv.second))) {
1180 signalPassFailure();
1181 return;
1182 }
1183 }
1184
1185 // An sret slot or an indirect argument is a pointer the source never
1186 // wrote, and an ellipsis can carry one the declared parameters do not
1187 // describe. The callee reads and writes that memory whatever const or
1188 // pure recorded about it, so the recorded effects have to widen.
1189 for (auto &kv : classifications) {
1190 cir::FuncOp func = kv.first;
1191 if (hasIndirectSlot(kv.second) || func.getFunctionType().isVarArg())
1192 widenForArgMemory(func);
1193 }
1194
1195 // Rewrite each function together with every direct call to it and every op
1196 // holding its address. By the time we move on to function F+1, F's
1197 // signature and every reference to F have already been brought into
1198 // alignment, and F+1..FN are still in their original (mutually consistent)
1199 // form, so the IR is verifier-clean at every outer-iteration boundary.
1200 //
1201 // There is still a brief inner window where F's signature has been
1202 // rewritten but its references have not yet caught up -- we have no way to
1203 // mutate both sides of a call atomically. No verifier runs inside the
1204 // pass, and at pass exit the module is verifier-clean. Fusing the inner
1205 // loops here keeps the invalid window per-function rather than module-wide.
1206 OpBuilder builder(ctx);
1207 for (auto &kv : classifications) {
1208 cir::FuncOp func = kv.first;
1209 const FunctionClassification &fc = kv.second;
1210 if (failed(rewriteCtx.rewriteFunctionDefinition(func, fc, builder))) {
1211 signalPassFailure();
1212 return;
1213 }
1214 for (Operation *callOp : callers.lookup(func)) {
1215 const FunctionClassification *callFc = &fc;
1216 if (auto it = variadicCallSites.find(callOp);
1217 it != variadicCallSites.end()) {
1218 callFc = &it->second;
1219 assert(classifiesSamePrefix(fc, *callFc) &&
1220 "a call site's declared parameters must be classified the same "
1221 "way as the callee's");
1222 }
1223 if (hasIndirectSlot(*callFc))
1224 widenForArgMemory(cast<cir::CIRCallOpInterface>(callOp));
1225 if (failed(rewriteCtx.rewriteCallSite(callOp, *callFc, builder))) {
1226 signalPassFailure();
1227 return;
1228 }
1229 }
1230 for (cir::GetGlobalOp addrOp : addressTakers.lookup(func))
1231 rewriteCtx.rewriteFunctionAddress(addrOp, func, builder);
1232 }
1233
1234 // Rewrite indirect call sites. The callee is opaque, so classify from the
1235 // function pointer's pointee FuncType and let rewriteCallSite retype the
1236 // callee pointer to match the coerced signature. Collect the calls first:
1237 // when an sret rewrite reuses a single-use store's destination as the return
1238 // slot it erases that store, which is the operation a live walk has already
1239 // cached as the next one to visit.
1240 SmallVector<cir::CIRCallOpInterface> indirectCalls;
1241 moduleOp.walk([&](cir::CIRCallOpInterface c) {
1242 if (c.isIndirect())
1243 indirectCalls.push_back(c);
1244 });
1245 for (cir::CIRCallOpInterface c : indirectCalls) {
1246 // classification-attr mode injects a per-function classification, which
1247 // cannot describe a callee resolved at run time. Report it rather than
1248 // leave the indirect call unrewritten while direct calls are coerced.
1249 if (!classificationAttr.empty()) {
1250 c->emitOpError() << "indirect call cannot be classified in the "
1251 "'classification-attr' driver mode";
1252 signalPassFailure();
1253 return;
1254 }
1255 cir::FuncType funcTy = getIndirectCalleeType(c);
1256 auto classifySignature =
1257 [&](mlir::TypeRange argTypes) -> std::optional<FunctionClassification> {
1258 // A callee resolved at run time carries no features of its own, so the
1259 // level comes from the function containing the call, which is the
1260 // declaration classic arranges every call site from.
1261 if (isX86)
1262 return classifyX86_64Signature(
1263 funcTy.getReturnType(), argTypes, requiredArgs(funcTy), ctx, dl,
1264 *x86TypeMapper,
1265 x86TargetFor(avxLevelFor(c->getParentOfType<cir::FuncOp>())),
1266 moduleOp, [&]() { return c->emitOpError(); });
1267 return withReturnVoidness(
1268 mlir::abi::test::classify(argTypes, funcTy.getReturnType(), dl),
1269 funcTy.getReturnType());
1270 };
1271
1272 // An argument passed through an ellipsis has no counterpart in the
1273 // pointee's parameter list. On x86_64 such a call is classified from its
1274 // own operands, as a direct one is. Under target=test it is classified
1275 // from the pointee alone, and rewriteCallSite reports the call.
1276 bool classifyCallSite =
1277 isX86 && c.getNumArgOperands() > funcTy.getNumInputs();
1278 std::optional<FunctionClassification> fc =
1279 classifyCallSite
1280 ? classifyX86_64VariadicCall(
1281 c, funcTy, dl, *x86TypeMapper,
1282 x86TargetFor(avxLevelFor(c->getParentOfType<cir::FuncOp>())),
1283 moduleOp)
1284 : classifySignature(funcTy.getInputs());
1285 if (!fc) {
1286 signalPassFailure();
1287 return;
1288 }
1289 if (hasIndirectSlot(*fc))
1290 widenForArgMemory(c);
1291 if (failed(rewriteCtx.rewriteCallSite(c.getOperation(), *fc, builder))) {
1292 signalPassFailure();
1293 return;
1294 }
1295 }
1296
1297 if (isX86) {
1298 // Collect the fetches before rewriting any, because rewriting one erases
1299 // it, and a live walk holds the op it is about to visit next.
1300 SmallVector<cir::VAArgOp> vaArgs;
1301 moduleOp.walk([&](cir::VAArgOp v) { vaArgs.push_back(v); });
1302 for (cir::VAArgOp v : vaArgs) {
1303 cir::FuncOp enclosing = v->getParentOfType<cir::FuncOp>();
1304 std::optional<ArgClassification> ac = classifyX86_64VarArgType(
1305 v.getType(), ctx, dl, *x86TypeMapper,
1306 x86TargetFor(avxLevelFor(enclosing)), moduleOp,
1307 [&]() { return v->emitOpError(); });
1308 if (!ac) {
1309 signalPassFailure();
1310 return;
1311 }
1312 if (failed(rewriteCtx.rewriteVAArg(v.getOperation(), *ac, builder))) {
1313 signalPassFailure();
1314 return;
1315 }
1316 }
1317 }
1318}
1319
1320} // namespace
1321
1322std::unique_ptr<Pass> mlir::createCallConvLoweringPass() {
1323 return std::make_unique<CallConvLoweringPass>();
1324}
1325
1327 cir::CallConvTarget target, llvm::abi::X86AVXABILevel x86AvxAbiLevel,
1329 const llvm::abi::X86ABICompatInfo &x86AbiCompat) {
1330 CallConvLoweringOptions options;
1331 options.target = target;
1332 options.x86AvxAbiLevel = x86AvxAbiLevel;
1333 options.allowsX86TargetAttrAvx = allowsX86TargetAttrAvx;
1334 return std::make_unique<CallConvLoweringPass>(options, x86AbiCompat);
1335}
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:149
bool isUnion() const
Definition CIRTypes.h:175
bool isComplete() const
Definition CIRTypes.h:168
bool isEmptyForABI() const
Whether no member holds data.
Definition CIRTypes.cpp:702
llvm::ArrayRef< mlir::Type > getMembers() const
Definition CIRTypes.cpp:609
static llvm::SmallVector< RecordMemberKind > getAllDataKinds(llvm::ArrayRef< mlir::Type > members)
One Data kind per member.
Definition CIRTypes.cpp:162
mlir::StringAttr getName() const
Definition CIRTypes.cpp:614
llvm::ArrayRef< RecordMemberKind > getMemberKinds() const
Definition CIRTypes.cpp:634
uint64_t getElementOffset(const mlir::DataLayout &dataLayout, unsigned idx) const
Definition CIRTypes.cpp:667
RecordLayoutAttr tryGetRecordLayout(mlir::ModuleOp mod, mlir::StringAttr name)
Same lookup as getRecordLayout, but returns a null attribute instead of asserting when the record has...
static bool allowsX86TargetAttrAvx(const llvm::Triple &triple, clang::LangOptions::ClangABI compat)
Whether __attribute__((target(...))) on a function may raise its AVX ABI level above the command line...
Definition CIRPasses.cpp:45
cir::FPTypeInterface getFloatingPointType(const llvm::fltSemantics &sem, mlir::MLIRContext *ctx)
Returns the CIR floating-point type for the given semantics, or a null type if CIR has no type for it...
Definition CIRTypes.cpp:42
cir::FuncType getIndirectCalleeType(cir::CIRCallOpInterface call)
The signature the indirect call call reaches its callee through.
CallConvTarget
The ABI target whose calling-convention rules drive CallConvLowering.
Definition Passes.h:23
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:218
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Definition Utils.h:57
@ Default
Set to the current date and time.
std::unique_ptr< Pass > createCallConvLoweringPass()
static bool addressSpace()
static bool opFuncMultiVersioning()