llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: adams381

<details>
<summary>Changes</summary>

Fourth PR in the split of #<!-- -->192119/#<!-- -->192124. Implements the
Direct-with-coercion path in CallConvLowering and picks off
andykaylor's five inline review comments from the original PR.

The new cir.reinterpret_cast op is for same-bit-width in-register
reinterpretation (vector&lt;2 x float&gt; &lt;-&gt; complex&lt;float&gt;).
emitCoercion uses it when source and destination differ only in
vector-vs-non-vector shape and have identical bit width, instead
of going through memory. For everything else (records, or shape
doesn't match) the helper still does alloca/store/ptr-cast/load.

Andy's comments, in order:
- Temporary alloca alignment is now max(srcAlign, dstAlign) from
  DataLayout instead of hardcoded.
- The alloca lives in the entry block via InsertionGuard so it
  composes with HoistAllocas regardless of pipeline order.
- isVolatile kept as UnitAttr-absence with an inline comment.
- vector&lt;-&gt;complex now uses cir.reinterpret_cast.
- Memory path has three new .cir tests covering it.

CallConvLowering needed splitting into three phases
(function-def coercion / call-site rewriting / Ignore cleanup)
because block-arg type changes from Direct-with-coerce confused
the earlier ordering: Ignore'd args were getting alloca/load
chains synthesized for call-site uses that were about to be
dropped anyway.

LowerToLLVM gets a stub for the new op: bitcast for same-shape
converted types, error-with-message for aggregates. We don't
produce aggregates from CallConvLowering today, so the error
path is only reachable from hand-written IR; follow-up patch can
add an extract/insert lowering if needed.

Co-authored-by: Cursor &lt;cursoragent@<!-- -->cursor.com&gt;



---

Patch is 100.75 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/195879.diff


32 Files Affected:

- (modified) clang/docs/CIR/ABILowering.rst (+40) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+48) 
- (modified) clang/include/clang/CIR/Dialect/Passes.h (+1) 
- (modified) clang/include/clang/CIR/Dialect/Passes.td (+46-6) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+22) 
- (modified) clang/lib/CIR/Dialect/Transforms/CMakeLists.txt (+3) 
- (added) clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp (+198) 
- (added) 
clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp (+570) 
- (added) 
clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.h (+77) 
- (modified) clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt 
(+2) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+39) 
- (added) clang/test/CIR/IR/reinterpret-cast.cir (+28) 
- (added) clang/test/CIR/Transforms/abi-lowering/Inputs/test-datalayout.cir 
(+17) 
- (added) clang/test/CIR/Transforms/abi-lowering/coerce-int-to-record.cir (+59) 
- (added) clang/test/CIR/Transforms/abi-lowering/coerce-record-to-int.cir (+50) 
- (added) 
clang/test/CIR/Transforms/abi-lowering/coerce-record-to-record-via-memory.cir 
(+34) 
- (added) 
clang/test/CIR/Transforms/abi-lowering/coerce-vector-to-complex-reinterpret.cir 
(+42) 
- (added) clang/test/CIR/Transforms/abi-lowering/datalayout-missing-error.cir 
(+17) 
- (added) clang/test/CIR/Transforms/abi-lowering/declaration-rewrite.cir (+34) 
- (added) 
clang/test/CIR/Transforms/abi-lowering/direct-passthrough-injection.cir (+42) 
- (added) 
clang/test/CIR/Transforms/abi-lowering/direct-passthrough-test-target.cir (+35) 
- (added) clang/test/CIR/Transforms/abi-lowering/extend-return.cir (+41) 
- (added) clang/test/CIR/Transforms/abi-lowering/extend-signed-arg.cir (+40) 
- (added) clang/test/CIR/Transforms/abi-lowering/extend-unsigned-arg.cir (+36) 
- (added) clang/test/CIR/Transforms/abi-lowering/ignore-arg.cir (+39) 
- (added) clang/test/CIR/Transforms/abi-lowering/ignore-return.cir (+48) 
- (modified) clang/tools/cir-opt/cir-opt.cpp (+4) 
- (added) mlir/include/mlir/ABI/Targets/Test/TestTarget.h (+98) 
- (modified) mlir/lib/ABI/CMakeLists.txt (+1) 
- (added) mlir/lib/ABI/Targets/Test/TestTarget.cpp (+251) 
- (modified) mlir/unittests/ABI/CMakeLists.txt (+1) 
- (added) mlir/unittests/ABI/TestTargetTest.cpp (+317) 


``````````diff
diff --git a/clang/docs/CIR/ABILowering.rst b/clang/docs/CIR/ABILowering.rst
index 59f0bb4f9a646..74457be5c8e6d 100644
--- a/clang/docs/CIR/ABILowering.rst
+++ b/clang/docs/CIR/ABILowering.rst
@@ -531,6 +531,46 @@ options or configuration.  The dependency direction is: 
the MLIR ABI pass
 depends on ``llvm/lib/ABI``; there is no reverse dependency from the ABI 
library
 to MLIR dialects.
 
+CIR Pass Pipeline Position
+--------------------------
+
+For the CIR dialect, the calling-convention lowering pass is named
+``cir-call-conv-lowering`` and runs late in the CIR-to-LLVM pipeline:
+
+1. ``cir-target-lowering`` legalizes target-specific operations (e.g.
+   atomic synchronization scopes).
+2. ``cir-cxxabi-lowering`` lowers C++-specific high-level types (member
+   pointers, vtable lookups, etc.) to ABI-specific representations.
+3. ``cir-call-conv-lowering`` rewrites function signatures and call sites
+   to match the target ABI's calling convention rules.
+
+``cir-call-conv-lowering`` requires a ``dlti.dl_spec`` attribute on the
+module so it can query type sizes and alignments through MLIR's
+``DataLayout``.  When the attribute is missing, the pass emits a
+diagnostic and fails rather than silently using a default layout.
+
+The pass places any temporary allocas it needs (for argument coercion,
+sret slots, etc.) directly in the function entry block, so it does not
+rely on a subsequent ``cir-hoist-allocas`` run to position them
+correctly.  This invariant means ``cir-hoist-allocas`` may run either
+before or after ``cir-call-conv-lowering`` without changing observable
+behavior.
+
+The pass takes one of two driver modes via pass options:
+
+- ``target=<name>`` selects a real ABI target.  The first supported value
+  is ``test`` (the MLIR test target in ``mlir/lib/ABI/Targets/Test/``,
+  used for testing the rewriter without depending on the in-progress
+  LLVM ABI library targets).  Real targets (``x86_64``, ``aarch64``,
+  ...) will be added as the LLVM ABI library ships them.
+- ``classification-attr=<name>`` reads a pre-built ``FunctionClassifica
+  tion`` from a ``DictionaryAttr`` named ``<name>`` on each ``cir.func``
+  and rewrites accordingly.  This driver is for tests that need to
+  exercise rewriter behavior against arbitrary classifications without
+  routing through any real classifier.
+
+Exactly one of the two options must be set.
+
 Open Questions
 ==============
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 97d623ba5e6d9..1f0cb759864f8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -266,6 +266,54 @@ def CIR_CastOp : CIR_Op<"cast", [
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// ReinterpretCastOp
+//===----------------------------------------------------------------------===//
+
+def CIR_ReinterpretCastOp : CIR_Op<"reinterpret_cast", [Pure]> {
+  let summary = "Reinterpret a value as a different same-bit-width type";
+  let description = [{
+    The `cir.reinterpret_cast` operation reinterprets the bits of its source
+    value as a different type, with no IR-level cost.  It is used by the
+    calling-convention lowering pass to coerce between same-bit-width types
+    that have an LLVM-IR-level shape mismatch but identical in-register
+    representation -- for example, between `!cir.vector<2 x !cir.float>` and
+    `!cir.complex<!cir.float>`, both of which lower to the same LLVM IR
+    representation but have distinct CIR types.
+
+    Unlike `cir.cast bitcast`, which is overloaded for pointer-to-pointer
+    bitcasts and several other use cases, `cir.reinterpret_cast` is reserved
+    for in-register value reinterpretation only.  The result type must
+    differ from the source type; otherwise the op is meaningless and the
+    folder removes it.
+
+    **Invariant** (not currently enforced by the verifier): the source and
+    destination types must have the same bit width per the module's
+    DataLayout, and they must use the same in-register lane order on the
+    target.  Producers (e.g. CallConvLowering's coerce-in-registers path)
+    are responsible for ensuring this; a follow-up patch will move the
+    bit-width check into the verifier once the design question of
+    DataLayout-aware op verifiers is resolved.
+
+    Example:
+
+    ```
+    %c = cir.reinterpret_cast %v
+       : !cir.vector<2 x !cir.float> -> !cir.complex<!cir.float>
+    ```
+  }];
+
+  let arguments = (ins CIR_AnyType:$src);
+  let results = (outs CIR_AnyType:$result);
+
+  let assemblyFormat = [{
+    $src `:` type($src) `->` type($result) attr-dict
+  }];
+
+  let hasVerifier = 1;
+  let hasFolder = 1;
+}
+
 
//===----------------------------------------------------------------------===//
 // DynamicCastOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/Passes.h 
b/clang/include/clang/CIR/Dialect/Passes.h
index d441dfcbc6c14..a68f7b621f5d8 100644
--- a/clang/include/clang/CIR/Dialect/Passes.h
+++ b/clang/include/clang/CIR/Dialect/Passes.h
@@ -27,6 +27,7 @@ std::unique_ptr<Pass> createCIRSimplifyPass();
 std::unique_ptr<Pass> createCIREHABILoweringPass();
 std::unique_ptr<Pass> createCXXABILoweringPass();
 std::unique_ptr<Pass> createTargetLoweringPass();
+std::unique_ptr<Pass> createCallConvLoweringPass();
 std::unique_ptr<Pass> createHoistAllocasPass();
 std::unique_ptr<Pass> createLoweringPreparePass();
 std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx);
diff --git a/clang/include/clang/CIR/Dialect/Passes.td 
b/clang/include/clang/CIR/Dialect/Passes.td
index 32cd182aacec7..cb3c78d590a42 100644
--- a/clang/include/clang/CIR/Dialect/Passes.td
+++ b/clang/include/clang/CIR/Dialect/Passes.td
@@ -108,7 +108,7 @@ def TargetLowering : Pass<"cir-target-lowering", 
"mlir::ModuleOp"> {
 
       1. The `TargetLowering` pass.
       2. The `CXXABILowering` pass.
-      3. The `CallConvLowering` pass (not implemented yet).
+      3. The `CallConvLowering` pass.
 
     The `TargetLowering` pass acts more like a legalization pass. It ensures
     every operation in CIR conforms to the target's constraints. An example
@@ -117,11 +117,11 @@ def TargetLowering : Pass<"cir-target-lowering", 
"mlir::ModuleOp"> {
     any atomic operations with a different synchronization scope would be
     transformed to use the system-wide scope in this pass.
 
-    The `CXXABILowering` pass and the (not yet implemented) `CallConvLowering`
-    pass transform the CIR according to the target's ABI requirements. The
-    former handles all ABI-related lowering except for calling convention
-    handling, which is handled specifically in the latter. Example
-    transformations that the `CXXABILowering` pass could make include:
+    The `CXXABILowering` pass and the `CallConvLowering` pass transform the
+    CIR according to the target's ABI requirements. The former handles all
+    ABI-related lowering except for calling convention handling, which is
+    handled specifically in the latter. Example transformations that the
+    `CXXABILowering` pass could make include:
 
       - Replace C/C++ types that have an ABI-defined layout with more
         fundamental types corresponding to the ABI requirements. For example,
@@ -195,4 +195,44 @@ def IdiomRecognizer : Pass<"cir-idiom-recognizer", 
"mlir::ModuleOp"> {
   let dependentDialects = ["cir::CIRDialect"];
 }
 
+def CallConvLowering : Pass<"cir-call-conv-lowering", "mlir::ModuleOp"> {
+  let summary = "Lower CIR function signatures and call sites to match target 
ABI";
+  let description = [{
+    This pass rewrites `cir.func` signatures and `cir.call` sites to match the
+    target ABI's calling convention requirements (extension attributes, struct
+    coercion, sret/byval indirect passing, struct flattening, etc.).
+
+    The pass requires a `dlti.dl_spec` attribute on the module so it can query
+    the data layout for sizes and alignments.
+
+    Two driver modes select how each function's classification is computed:
+
+    - `target=<name>` selects an ABI target.  Currently only `"test"` (the
+      MLIR test target in `mlir/lib/ABI/Targets/Test/`) is supported.  Real
+      targets (x86_64, AArch64, ...) will be added once the LLVM ABI library
+      ships them.
+    - `classification-attr=<name>` reads a `DictionaryAttr` named `<name>`
+      from each `cir.func` and parses it via the test-target injection
+      helper.  Used by tests to inject arbitrary classifications without
+      depending on a real ABI target.
+
+    Exactly one of the two options must be set.
+
+    Pipeline position: this pass runs after `CXXABILowering` (so member
+    pointers and similar C++ types are already lowered) and after
+    `HoistAllocas` is unnecessary because this pass places its own temporary
+    allocas in the entry block.
+  }];
+  let constructor = "mlir::createCallConvLoweringPass()";
+  let dependentDialects = ["cir::CIRDialect"];
+  let options = [
+    Option<"target", "target", "std::string", /*default=*/"\"\"",
+           "Target whose ABI rules drive classification (currently: test)">,
+    Option<"classificationAttr", "classification-attr", "std::string",
+           /*default=*/"\"\"",
+           "Function attribute name carrying a pre-built 
FunctionClassification "
+           "DictionaryAttr (alternative to target=, used by tests)">,
+  ];
+}
+
 #endif // CLANG_CIR_DIALECT_PASSES_TD
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 7386819d8fce9..80c3a3ecaea4a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -821,6 +821,28 @@ static Value tryFoldCastChain(cir::CastOp op) {
   return {};
 }
 
+//===----------------------------------------------------------------------===//
+// ReinterpretCastOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::ReinterpretCastOp::verify() {
+  // The op is meaningless for identical types -- the folder is the right
+  // way to remove it -- but we accept it at the verifier level so that
+  // peephole code (e.g. pattern rewriters that round-trip values) doesn't
+  // need a type-equality guard.  Producers should still avoid emitting
+  // it for matching types.
+  //
+  // The same-bit-width invariant is documented on the op but not yet
+  // checked here; see the op description for the rationale.
+  return success();
+}
+
+OpFoldResult cir::ReinterpretCastOp::fold(FoldAdaptor adaptor) {
+  if (getSrc().getType() == getType())
+    return getSrc();
+  return {};
+}
+
 OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
   if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
     // Propagate poison value
diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt 
b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
index 092ccfac7ddb7..b3fa7375eaafa 100644
--- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(TargetLowering)
 
 add_clang_library(MLIRCIRTransforms
+  CallConvLoweringPass.cpp
   CIRCanonicalize.cpp
   CIRSimplify.cpp
   CXXABILowering.cpp
@@ -19,7 +20,9 @@ add_clang_library(MLIRCIRTransforms
   clangAST
   clangBasic
 
+  MLIRABI
   MLIRAnalysis
+  MLIRDLTIDialect
   MLIRIR
   MLIRPass
   MLIRTransformUtils
diff --git a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp 
b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
new file mode 100644
index 0000000000000..5131bcfa4316a
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
@@ -0,0 +1,198 @@
+//===- CallConvLoweringPass.cpp - Lower CIR to ABI calling convention ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass walks every cir.func and cir.call in the module, computes a
+// FunctionClassification for it (via either an ABI target or a pre-built
+// classification injected as a function attribute), and dispatches to
+// CIRABIRewriteContext to perform the actual IR rewriting.
+//
+// Two driver modes (mutually exclusive):
+//
+//   target=test
+//     Use the MLIR test ABI target (mlir/lib/ABI/Targets/Test/) to classify
+//     each function.  Predictable rules that approximate x86_64 SysV.  Real
+//     targets (x86_64, AArch64) will be added once the LLVM ABI library
+//     ships them.
+//
+//   classification-attr=<name>
+//     Read a DictionaryAttr named <name> from each cir.func and parse it via
+//     mlir::abi::test::parseClassificationAttr.  Used by tests to inject any
+//     classification (including shapes the test target itself does not
+//     produce) without depending on a real ABI target.
+//
+// The pass requires a `dlti.dl_spec` attribute on the module so the
+// classifier can query type sizes and alignments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PassDetail.h"
+#include "TargetLowering/CIRABIRewriteContext.h"
+
+#include "mlir/ABI/ABIRewriteContext.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/Interfaces/DataLayoutInterfaces.h"
+#include "mlir/Pass/Pass.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+
+using namespace mlir;
+using namespace mlir::abi;
+using namespace cir;
+
+namespace mlir {
+#define GEN_PASS_DEF_CALLCONVLOWERING
+#include "clang/CIR/Dialect/Passes.h.inc"
+} // namespace mlir
+
+namespace {
+
+struct CallConvLoweringPass
+    : public impl::CallConvLoweringBase<CallConvLoweringPass> {
+  using CallConvLoweringBase::CallConvLoweringBase;
+  void runOnOperation() override;
+};
+
+/// Classify \p func using whichever driver mode is configured.  Returns
+/// std::nullopt and emits an error on the function if classification fails
+/// (e.g. injection-driver mode but the function is missing the attribute,
+/// or the attribute is malformed).
+std::optional<FunctionClassification>
+classifyFunction(cir::FuncOp func, const DataLayout &dl, StringRef target,
+                 StringRef classificationAttrName) {
+  ArrayRef<Type> argTypes = func.getFunctionType().getInputs();
+  Type returnType = func.getFunctionType().getReturnType();
+
+  if (!classificationAttrName.empty()) {
+    auto attr = func->getAttrOfType<DictionaryAttr>(classificationAttrName);
+    if (!attr) {
+      func.emitOpError()
+          << "missing classification attribute '" << classificationAttrName
+          << "' (CallConvLowering driver mode 'classification-attr')";
+      return std::nullopt;
+    }
+    return mlir::abi::test::parseClassificationAttr(
+        attr, [&]() { return func.emitOpError(); });
+  }
+
+  if (target == "test")
+    return mlir::abi::test::classify(argTypes, returnType, dl);
+
+  func.emitOpError() << "unknown target '" << target << "' (supported: test)";
+  return std::nullopt;
+}
+
+/// Find the cir.func declaration matching a cir.call's callee, if any.
+/// Returns nullptr if the callee is indirect or the symbol cannot be
+/// resolved (in which case the call is left alone).
+cir::FuncOp lookupCallee(cir::CallOp call, ModuleOp module) {
+  FlatSymbolRefAttr callee = call.getCalleeAttr();
+  if (!callee)
+    return nullptr;
+  return module.lookupSymbol<cir::FuncOp>(callee.getValue());
+}
+
+void CallConvLoweringPass::runOnOperation() {
+  ModuleOp module = getOperation();
+  MLIRContext *ctx = &getContext();
+
+  if (target.empty() == classificationAttr.empty()) {
+    module.emitOpError() << "CallConvLowering requires exactly one of "
+                            "'target' or 'classification-attr' pass options";
+    signalPassFailure();
+    return;
+  }
+
+  if (!module->hasAttr(DLTIDialect::kDataLayoutAttrName)) {
+    module.emitOpError()
+        << "CallConvLowering requires a DataLayout (dlti.dl_spec attribute "
+           "on the module)";
+    signalPassFailure();
+    return;
+  }
+
+  DataLayout dl(module);
+  CIRABIRewriteContext rewriteCtx(module, dl);
+
+  // Pre-compute classifications for every cir.func so that call-site
+  // rewriting can find them (call site uses callee's classification).
+  llvm::MapVector<cir::FuncOp, FunctionClassification> classifications;
+  bool anyFailed = false;
+  module.walk([&](cir::FuncOp f) {
+    auto fc = classifyFunction(f, dl, target, classificationAttr);
+    if (!fc) {
+      anyFailed = true;
+      return;
+    }
+    classifications.insert({f, std::move(*fc)});
+  });
+  if (anyFailed) {
+    signalPassFailure();
+    return;
+  }
+
+  OpBuilder rewriter(ctx);
+
+  // Three-phase rewrite.  Each phase needs the previous one to be complete
+  // across every function before it can run, so they're three separate
+  // sweeps over the module:
+  //
+  //   1. rewriteFunctionDefinition: in-body coercion only.  Block-arg
+  //      types for Direct-with-coerce / Extend args change here, and
+  //      replaceAllUsesExcept routes existing uses (including in-body
+  //      cir.call operands) over to the adapted (original-type) value.
+  //      Ignore handling and signature finalization are deferred.
+  //   2. rewriteCallSite: each call site coerces args, drops Ignore'd
+  //      args, and swaps the call to the lowered signature.  Now Ignore'd
+  //      block args have no remaining uses.
+  //   3. finalizeFunctionDefinition: erase the now-use-empty Ignore'd
+  //      block args, drop Ignore'd return operands, finalize the function
+  //      signature, and attach the llvm.signext / llvm.zeroext attrs.
+  //
+  // Splitting (1) and (3) avoids synthesizing dead alloca/load chains
+  // for Ignore'd args whose uses were going to be dropped by (2) anyway.
+
+  for (auto &kv : classifications) {
+    if (failed(rewriteCtx.rewriteFunctionDefinition(kv.first, kv.second,
+                                                    rewriter))) {
+      signalPassFailure();
+      return;
+    }
+  }
+
+  SmallVector<cir::CallOp> calls;
+  module.walk([&](cir::CallOp c) { calls.push_back(c); });
+  for (cir::CallOp call : calls) {
+    cir::FuncOp callee = lookupCallee(call, module);
+    if (!callee)
+      continue;
+    auto it = classifications.find(callee);
+    if (it == classifications.end())
+      continue;
+    if (failed(rewriteCtx.rewriteCallSite(call, it->second, rewriter))) {
+      signalPassFailure();
+      return;
+    }
+  }
+
+  for (auto &kv : classifications) {
+    if (failed(rewriteCtx.finalizeFunctionDefinition(kv.first, kv.second,
+                                                     rewriter))) {
+      signalPassFailure();
+      return;
+    }
+  }
+}
+
+} // namespace
+
+std::unique_ptr<Pass> mlir::createCallConvLoweringPass() {
+  return std::make_unique<CallConvLoweringPass>();
+}
diff --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp
new file mode 100644
index 0000000000000..18937d694260b
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp
@@ -0,0 +1,570 @@
+//===- CIRABIRewriteContext.cpp - CIR ABI rewrite context ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRABIRewriteContext.h"
+#include "mlir/IR/Builders.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+
+using namespace cir;
+using namespace mlir;
+using namespace mlir::abi;
+
+namespace {
+
+bool needsRewrite(const FunctionClassification &fc) {
+  // Direct without coercion is a true pass-through; any other kind (or a
+  // coerced Direct) means the rewriter must touch the IR.  Extend is
+  // technically attribute-only at the IR level but still counts because the
+  // attribute attachment changes observable behav...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/195879
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to