================
@@ -0,0 +1,1617 @@
+# ClangIR ABI Lowering - Design Document
+
+**Version**: 1.0  
+**Date**: January 2026  
+**Authors**: Adam Smith (CIR Team)  
+**Status**: Complete Specification - Ready for Implementation  
+**Target**: x86_64 and AArch64 (primary), extensible to other targets
+
+---
+
+## Quick Start: How to Read This Document
+
+**If you have 5 minutes**: Read Section I (Executive Summary)  
+**If you have 30 minutes**: Read Section I (Executive Summary) + Section V 
(Implementation Phases)  
+**If you have 2 hours**: Read the entire document  
+**If you're implementing**: Focus on Section IV (Architecture) and Section V 
(Phases)  
+**If you're reviewing for approval**: Focus on Section X (Open Questions) and 
Section XI (Success Metrics)  
+**If you're new to MLIR**: Read Section II (Background) first
+
+---
+
+## Document Purpose
+
+This document proposes a comprehensive design for creating an MLIR-agnostic 
calling convention lowering framework. The framework will:
+1. Enable CIR to perform ABI-compliant calling convention lowering
+2. Be reusable by other MLIR dialects (FIR, future dialects)
+3. Achieve parity with CIR incubator implementation for x86_64 and AArch64
+4. Integrate with or inform the GSoC ABI Lowering Library project
+
+## I. Executive Summary
+
+### 1.1 Problem Statement
+
+Calling convention lowering is currently implemented separately for each MLIR 
dialect that needs it. The CIR incubator has a partial implementation, but it's 
tightly coupled to CIR-specific types and operations, making it unsuitable for 
reuse by other dialects. This means that FIR (Fortran IR) and future MLIR 
dialects would need to duplicate this complex logic. While classic Clang 
codegen contains mature ABI lowering code, it cannot be reused directly because 
it's tightly coupled to Clang's AST representation and LLVM IR generation.
+
+### 1.2 Proposed Solution
+
+This design proposes a three-layer architecture that separates concerns and 
enables code reuse. The first layer contains pure ABI classification logic that 
is completely dialect-agnostic, operating only on abstract type 
representations. The second layer provides interface-based abstractions for 
querying type properties and layout information, allowing the classification 
logic to work with any dialect's types. The third layer handles 
dialect-specific operation rewriting, where each dialect implements its own 
operation creation logic while reusing the classification results from the 
lower layers.
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│                    MLIR-Agnostic ABI Lowering                       │
+│                         (Three-Layer Design)                        │
+└─────────────────────────────────────────────────────────────────────┘
+
+┌─────────────────────────────────────────────────────────────────────┐
+│ Layer 3: Dialect-Specific Operation Rewriting                       │
+│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │
+│  │ CIR Rewrite │  │ FIR Rewrite │  │ Other       │                  │
+│  │ Context     │  │ Context     │  │ Dialects    │                  │
+│  └──────┬──────┘  └───────┬─────┘  └────────┬────┘                  │
+│         │                 │                 │                       │
+│         └─────────────────┼─────────────────┘                       │
+│                           │                                         │
+└───────────────────────────┼─────────────────────────────────────────┘
+                            │ ABIRewriteContext Interface
+┌───────────────────────────┼─────────────────────────────────────────┐
+│ Layer 2: Interface-Based Type Abstractions                          │
+│                           │                                         │
+│  ┌────────────────────────▼──────────────────────────┐              │
+│  │ ABITypeInterface (TypeInterface)                  │              │
+│  │  - isRecord(), isInteger(), isFloatingPoint()     │              │
+│  │  - getNumFields(), getFieldType()                 │              │
+│  │  - getAlignof(), getSizeof()                      │              │
+│  └────────────────────────┬──────────────────────────┘              │
+│                           │                                         │
+└───────────────────────────┼─────────────────────────────────────────┘
+                            │ Abstract Type Queries
+┌───────────────────────────┼─────────────────────────────────────────┐
+│ Layer 1: Pure ABI Classification Logic (Dialect-Agnostic)           │
+│                           │                                         │
+│  ┌────────────────────────▼──────────────────────────┐              │
+│  │ ABIInfo (Target-Specific)                         │              │
+│  │  - classifyArgumentType()                         │              │
+│  │  - classifyReturnType()                           │              │
+│  └──────┬─────────────────────────┬──────────────┬───┘              │
+│         │                         │              │                  │
+│  ┌──────▼──────┐  ┌───────────────▼───┐  ┌───────▼──────┐           │
+│  │ X86_64      │  │ AArch64           │  │ Other        │           │
+│  │ ABIInfo     │  │ ABIInfo           │  │ Targets      │           │
+│  └─────────────┘  └───────────────────┘  └──────────────┘           │
+│                                                                     │
+│  Output: LowerFunctionInfo + ABIArgInfo                             │
+└─────────────────────────────────────────────────────────────────────┘
+
+```
+
+### 1.3 Key Benefits
+
+This architecture avoids duplicating complex ABI logic across MLIR dialects, 
reducing the maintenance burden and risk of inconsistencies. It maintains 
correct ABI compliance for all targets by reusing proven classification 
algorithms. The clear separation of concerns enables easier testing and 
validation, as each layer can be tested independently. Additionally, the design 
provides a straightforward migration path from the existing CIR incubator 
implementation.
+
+### 1.4 Success Criteria
+
+The framework will be considered successful when CIR can correctly lower 
x86_64 and AArch64 calling conventions with full ABI compliance. FIR should be 
able to adopt the same infrastructure with minimal dialect-specific adaptation. 
A comprehensive test suite must validate ABI compliance across all supported 
targets. Finally, the performance overhead should remain under 5% compared to a 
direct, dialect-specific implementation.
+
+## 2. Background and Context
+
+### 2.1 What is Calling Convention Lowering?
+
+Calling convention lowering transforms high-level function signatures to match 
target ABI (Application Binary Interface) requirements. When a function is 
declared at the source level with convenient, language-level types, these types 
must be translated into the specific register assignments, memory layouts, and 
calling sequences that the target architecture expects. For example, on x86_64 
System V ABI, a struct containing two 64-bit integers might be "expanded" into 
two separate arguments passed in registers, rather than being passed as a 
single aggregate:
+
+```
+// High-level CIR
+func @foo(i32, struct<i64, i64>) -> i32
+
+// After ABI lowering
+func @foo(i32 %arg0, i64 %arg1, i64 %arg2) -> i32
+//        ^       ^            ^        ^
+//        |       |            +--------+---- struct expanded into fields
+//        |       +---- first field passed in register
+//        +---- small integer passed in register
+```
+
+### 2.2 Why It's Complex
+
+Calling convention lowering is complex for several reasons. First, it's highly 
target-specific: each architecture (x86_64, AArch64, RISC-V, etc.) has 
different rules for how arguments are passed in registers versus memory. 
Second, it's type-dependent: the rules differ significantly for integers, 
floating-point values, structs, unions, and arrays. Third, it's 
context-sensitive: special handling is required for varargs functions, virtual 
method calls, and alternative calling conventions like vectorcall or 
preserve_most. Finally, the same target may have multiple ABI variants (e.g., 
x86_64 System V vs. Windows x64), adding another dimension of complexity.
+
+### 2.3 Existing Implementations
+
+#### Classic Clang CodeGen
+
+Classic Clang codegen (located in `clang/lib/CodeGen/`) transforms calling 
conventions during the AST-to-LLVM-IR lowering process. This implementation is 
mature and well-tested, handling all supported targets with comprehensive ABI 
coverage. However, it's tightly coupled to both Clang's AST representation and 
LLVM IR, making it difficult to reuse for MLIR-based frontends.
+
+#### CIR Incubator
+
+The CIR incubator includes a calling convention lowering pass in 
`clang/lib/CIR/Dialect/Transforms/TargetLowering/` that transforms CIR 
operations into ABI-lowered CIR operations as an MLIR pass. This implementation 
successfully adapted logic from classic codegen to work within the MLIR 
framework. However, it relies on CIR-specific types and operations, preventing 
reuse by other MLIR dialects.
+
+#### GSoC ABI Lowering Library (WIP)
+
+The Google Summer of Code project (PR #140112, not yet merged) proposes an 
independent ABI type system extracted from Clang's codegen. This library aims 
to be frontend-agnostic and reusable across different language frontends. While 
promising, it's still under development and currently focuses on Clang and LLVM 
IR rather than MLIR abstractions.
----------------
nikic wrote:

I think you need to provide a really good justification why you need something 
other than the LLVM ABI lowering library, other than "it's not upstreamed yet".

Having another abstraction around it on the MLIR level would be fine, but the 
core ABI logic should live in one place and one place only (which is the LLVM 
ABI library).

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

Reply via email to