clang 24.0.0git
CallConvLoweringPass.cpp File Reference
#include "CIRABIClassifier.h"
#include "PassDetail.h"
#include "TargetLowering/CIRABIRewriteContext.h"
#include "mlir/ABI/ABIRewriteContext.h"
#include "mlir/ABI/ABITypeMapper.h"
#include "mlir/ABI/Targets/Test/TestTarget.h"
#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "mlir/Pass/Pass.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/Passes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ABI/FunctionInfo.h"
#include "llvm/ABI/TargetInfo.h"
#include "llvm/ABI/Types.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <array>
#include "clang/CIR/Dialect/Passes.h.inc"

Go to the source code of this file.

Namespaces

namespace  mlir

Macros

#define GEN_PASS_DEF_CALLCONVLOWERING

Functions

static bool recordCanPassInRegs (ModuleOp modOp, cir::RecordType recTy)
 Whether a struct's declared argument-passing kind (from the module's record-layout metadata) allows it to be passed in registers.
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 the types they hold.
static bool sseUpCoerceSizeUnsupported (uint64_t recordBits, llvm::ArrayRef< mlir::Type > members, const DataLayout &dl)
 Whether the record's size has no SSEUP coerce.
static bool memberIsEmptyRecord (mlir::Type ty)
 Whether a member is an empty record, looking through arrays, since an array of empty records supplies no bytes either.
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 argument.
static bool hasIncompleteRecordByValue (mlir::Type ty)
 Whether ty, or an aggregate member/element reached by value (never through a pointer), is an incomplete record.
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 mlir::Type unwrapLongDoubleVectorElement (mlir::Type ty)
 Returns ty with a LongDoubleType vector element replaced by its underlying format, which is the element abiTypeToCIR builds for the same float.
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 bool hasIndirectSlot (const FunctionClassification &fc)
 Whether fc gives the callee access to memory through a pointer the ABI introduced: an sret slot for an indirect return, or an indirect argument.
template<typename OpTy>
static void widenForArgMemory (OpTy op)
 Record on op that the memory its pointer arguments address may be read and written.
static bool classifiesSamePrefix (const FunctionClassification &calleeFc, const FunctionClassification &callFc)
 Whether callFc classifies a call's leading arguments and its return exactly as calleeFc classifies the callee's declared parameters and return.
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.

Macro Definition Documentation

◆ GEN_PASS_DEF_CALLCONVLOWERING

#define GEN_PASS_DEF_CALLCONVLOWERING

Definition at line 66 of file CallConvLoweringPass.cpp.

Function Documentation

◆ abiTypeToCIR()

mlir::Type abiTypeToCIR ( const llvm::abi::Type * ty,
MLIRContext * ctx )
static

Convert an llvm::abi::Type coercion type back to a scalar CIR type.

Definition at line 295 of file CallConvLoweringPass.cpp.

References abiTypeToCIR(), cir::RecordType::getAllDataKinds(), and cir::getFloatingPointType().

Referenced by abiTypeToCIR(), and convertABIArgInfo().

◆ classifiesSamePrefix()

bool classifiesSamePrefix ( const FunctionClassification & calleeFc,
const FunctionClassification & callFc )
static

Whether callFc classifies a call's leading arguments and its return exactly as calleeFc classifies the callee's declared parameters and return.

A function definition and its call sites are rewritten from separate classifications, so the two would silently disagree on the wire format if an ellipsis argument could ever change how a declared parameter is passed.

Definition at line 888 of file CallConvLoweringPass.cpp.

◆ convertABIArgInfo()

std::optional< ArgClassification > convertABIArgInfo ( const llvm::abi::ArgInfo & info,
MLIRContext * ctx,
mlir::Type origTy )
static

Convert an llvm::abi::ArgInfo into the ArgClassification consumed by CIRABIRewriteContext.

Direct: the value passes in register(s). A coercion is forwarded in the cases where the value has to be rebuilt on the wire: an aggregate unpacked into the register(s) holding it, a scalar too wide for one register split into a tuple of them, a scalar the classifier widens to fill its eightbyte, a pointer moved into another address space, and a value whose live bytes start partway into its storage because a leading eightbyte holds no field (getDirectOffset). canFlatten follows the classifier's CanBeFlattened, so the rewriter splits a multi-field coerced struct into individual wire arguments unless the classifier asked to keep it intact. Any other scalar passes in its natural CIR type, which a null coercion denotes. A multi-field struct with a null coercion is its own coerced type, so the rewriter splits it into one wire argument per field as classic codegen does. A coercion this bridge cannot represent yields std::nullopt so the caller reports NYI rather than silently passing the value unchanged.

Extend: bool or a sub-register integer needs a signext/zeroext attribute. The x86_64 classifier (llvm/lib/ABI/Targets/X86.cpp) only returns Extend for an integer or bool operand, so any other origTy is asserted rather than silently handled.

Indirect: an aggregate that does not fit in registers, or a scalar too wide to fit (a _BitInt over 128 bits), is passed via a pointer (sret for returns, byval for arguments).

Ignore: a void return, or an empty record dropped from the signature.

Definition at line 592 of file CallConvLoweringPass.cpp.

References abiTypeToCIR(), and unwrapLongDoubleVectorElement().

Referenced by clang::CodeGen::CodeGenModule::computeABIInfoUsingLib().

◆ createABIClassifier()

std::unique_ptr< CIRABIClassifier > createABIClassifier ( cir::CallConvTarget target,
StringRef classificationAttrName,
const DataLayout & dl,
ModuleOp modOp,
const ABIClassifierOptions & options )
static

Build the classifier the pass options select.

Exactly one of target and classificationAttrName is set, which runOnOperation checks before calling.

Definition at line 969 of file CallConvLoweringPass.cpp.

References cir::AMDGPU, cir::createAMDGPUABIClassifier(), cir::createInjectedABIClassifier(), cir::createTestTargetABIClassifier(), cir::createX86_64ABIClassifier(), cir::None, cir::Test, and cir::X86_64.

◆ hasIncompleteRecordByValue()

bool hasIncompleteRecordByValue ( mlir::Type ty)
static

Whether ty, or an aggregate member/element reached by value (never through a pointer), is an incomplete record.

Such a record has no known layout, so no eightbyte classification can be built for it.

Definition at line 153 of file CallConvLoweringPass.cpp.

References hasIncompleteRecordByValue().

Referenced by hasIncompleteRecordByValue().

◆ hasIndirectSlot()

bool hasIndirectSlot ( const FunctionClassification & fc)
static

Whether fc gives the callee access to memory through a pointer the ABI introduced: an sret slot for an indirect return, or an indirect argument.

Definition at line 860 of file CallConvLoweringPass.cpp.

◆ isSupportedType()

bool isSupportedType ( mlir::Type ty,
const DataLayout & dl )
static

The CIR types the x86_64 bridge handles.

Scalars: an integer up to 128 bits (including __int128), a _BitInt of any width, pointer, vtable pointer, bool, void, or any floating-point type. Aggregates: a complete struct or union whose members are all themselves supported, or an array of a supported element type. Also a _Complex, or a fixed-width vector, of a supported element type. Everything else is reported NYI at the reject() choke point in classifyX86_64Function.

Definition at line 169 of file CallConvLoweringPass.cpp.

References cir::MissingFeatures::addressSpace(), isSupportedType(), kind, memberIsEmptyRecord(), and sseUpCoerceSizeUnsupported().

Referenced by isSupportedType().

◆ mapCIRType()

const llvm::abi::Type * mapCIRType ( mlir::Type type,
mlir::abi::ABITypeMapper & typeMapper,
const DataLayout & dl,
ModuleOp modOp )
static

Map a CIR type to an llvm::abi::Type.

classifySignature pre-filters the signature, so only the scalar and struct/array types handled here can reach this function.

Definition at line 364 of file CallConvLoweringPass.cpp.

References cir::MissingFeatures::addressSpace(), cir::RecordType::getElementOffset(), cir::RecordType::getMemberKinds(), cir::RecordType::getMembers(), cir::RecordType::isEmptyForABI(), cir::RecordType::isUnion(), kind, mapCIRType(), memberIsEmptyRecord(), recordCanPassInRegs(), and recordDeclaredAlign().

Referenced by mapCIRType().

◆ mayReachSseUp()

bool mayReachSseUp ( mlir::Type ty,
const DataLayout & dl )
static

Whether the classifier could give this type the SSEUP class, looking through arrays and records at the types they hold.

Definition at line 93 of file CallConvLoweringPass.cpp.

References mayReachSseUp().

Referenced by mayReachSseUp(), and sseUpCoerceSizeUnsupported().

◆ memberIsEmptyRecord()

bool memberIsEmptyRecord ( mlir::Type ty)
static

Whether a member is an empty record, looking through arrays, since an array of empty records supplies no bytes either.

Definition at line 129 of file CallConvLoweringPass.cpp.

Referenced by isSupportedType(), and mapCIRType().

◆ recordCanPassInRegs()

bool recordCanPassInRegs ( ModuleOp modOp,
cir::RecordType recTy )
static

Whether a struct's declared argument-passing kind (from the module's record-layout metadata) allows it to be passed in registers.

A record with no layout entry (e.g. an anonymous struct) has no C++ non-trivial reason to be forced to memory, so it defaults to can-pass-in-registers.

Definition at line 84 of file CallConvLoweringPass.cpp.

References cir::RecordType::getName(), and cir::tryGetRecordLayout().

Referenced by mapCIRType().

◆ recordDeclaredAlign()

llvm::Align recordDeclaredAlign ( ModuleOp modOp,
cir::RecordType recTy,
const DataLayout & dl )
static

A record's declared alignment, which the ABI uses for the byval and sret alignment of an indirect argument.

DataLayout derives alignment from the members, so it cannot see __attribute__((aligned(N))). The declared value comes from the module's record-layout metadata instead. CIRGen emits an entry for every record it names, so the computed fallback only serves hand-written CIR.

Definition at line 142 of file CallConvLoweringPass.cpp.

References cir::RecordType::getName(), and cir::tryGetRecordLayout().

Referenced by mapCIRType().

◆ sseUpCoerceSizeUnsupported()

bool sseUpCoerceSizeUnsupported ( uint64_t recordBits,
llvm::ArrayRef< mlir::Type > members,
const DataLayout & dl )
static

Whether the record's size has no SSEUP coerce.

That coerce is a vector as wide as the record, so only 128, 256 and 512 bits have one. A record past 512 bits classifies memory before any coerce is asked for.

Definition at line 116 of file CallConvLoweringPass.cpp.

References mayReachSseUp().

Referenced by isSupportedType().

◆ unwrapLongDoubleVectorElement()

mlir::Type unwrapLongDoubleVectorElement ( mlir::Type ty)
static

Returns ty with a LongDoubleType vector element replaced by its underlying format, which is the element abiTypeToCIR builds for the same float.

Definition at line 351 of file CallConvLoweringPass.cpp.

Referenced by convertABIArgInfo().

◆ widenForArgMemory()

template<typename OpTy>
void widenForArgMemory ( OpTy op)
static

Record on op that the memory its pointer arguments address may be read and written.

Absent effects already allow that, since an absent attribute means the effects are unknown, so they are left absent.

Definition at line 871 of file CallConvLoweringPass.cpp.