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