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