[clang] [ClangIR] Add ABI Lowering Design Document (PR #178326)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 28 10:35:09 PST 2026


https://github.com/adams381 updated https://github.com/llvm/llvm-project/pull/178326

>From 375f129ee610275fc796e8abec935d8d5c650842 Mon Sep 17 00:00:00 2001
From: Adam Smith <adams at nvidia.com>
Date: Tue, 27 Jan 2026 15:30:27 -0800
Subject: [PATCH 1/3] Add ClangIR ABI Lowering design document

This design document proposes a three-layer MLIR-agnostic framework for
calling convention lowering that enables code reuse across MLIR dialects.

Key highlights:
- Refactors CIR's existing implementation (~7,000 lines, 70% complete)
- Three-layer architecture: ABI classification, interfaces, dialect rewriting
- Timeline: 17-19 weeks (4-5 months)
- Per-dialect integration cost: < 2 weeks vs 3 months from scratch
- Primary targets: x86_64 System V, AArch64 PCS
- Testing: 650+ tests for ABI compliance

The framework will enable FIR (Fortran IR) and future MLIR dialects to
adopt calling convention lowering with minimal integration effort.
---
 clang/docs/ClangIRABILowering.md | 762 +++++++++++++++++++++++++++++++
 1 file changed, 762 insertions(+)
 create mode 100644 clang/docs/ClangIRABILowering.md

diff --git a/clang/docs/ClangIRABILowering.md b/clang/docs/ClangIRABILowering.md
new file mode 100644
index 0000000000000..7806a1a6d541c
--- /dev/null
+++ b/clang/docs/ClangIRABILowering.md
@@ -0,0 +1,762 @@
+# MLIR-Agnostic Calling Convention Lowering
+
+**Version**: 1.0  
+**Date**: January 2026  
+**Authors**: Adam Smith (CIR Team)  
+**Status**: Design Document - Ready for Community Review
+
+---
+
+## Abstract
+
+Calling convention lowering (transforming function signatures to match target ABI requirements) is currently duplicated across MLIR dialects. This document proposes a three-layer MLIR-agnostic framework that enables code reuse while maintaining dialect independence.
+
+**Key Points**:
+- **Problem**: Each MLIR dialect reimplements ABI lowering from scratch
+- **Solution**: Refactor CIR's existing implementation (~7,000 lines, 70% complete) into reusable infrastructure
+- **Timeline**: 17-19 weeks (4-5 months)
+- **Benefits**: Future dialects can integrate in < 2 weeks vs 3 months from scratch
+
+**Reading Guide**:
+- **5 minutes**: Read this Abstract and Architecture Overview
+- **30 minutes**: Add Implementation Plan and Critical Decisions
+- **2 hours**: Read entire document
+
+---
+
+## Table of Contents
+
+1. [Background and Motivation](#background-and-motivation)
+2. [Architecture Overview](#architecture-overview)
+3. [Core Interfaces](#core-interfaces)
+4. [Implementation Plan](#implementation-plan)
+5. [Target ABI Details](#target-abi-details)
+6. [Critical Decisions](#critical-decisions)
+7. [Testing Strategy](#testing-strategy)
+8. [Success Metrics](#success-metrics)
+9. [References](#references)
+
+---
+
+## Background and Motivation
+
+### What is Calling Convention Lowering?
+
+Calling convention lowering transforms high-level function signatures to match target ABI (Application Binary Interface) requirements.
+
+**Example** (x86_64 System V ABI):
+```mlir
+// 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
+```
+
+### Current State
+
+**Classic Clang CodeGen** (`clang/lib/CodeGen/`):
+- Mature implementation for all targets
+- **Limitation**: Tightly coupled to Clang AST and LLVM IR
+
+**CIR Incubator** (`clang/lib/CIR/Dialect/Transforms/TargetLowering/`):
+- ~7,000 lines of code, 70% complete
+- Supports x86_64 and AArch64
+- **Limitation**: CIR-specific types and operations
+
+**GSoC ABI Lowering Library** (PR #140112):
+- Frontend-agnostic approach
+- **Status**: Work in progress, not yet merged
+
+### The Problem
+
+- **Code Duplication**: Every MLIR dialect must reimplement ABI logic
+- **Maintenance Burden**: ABI bugs must be fixed in multiple places
+- **Inconsistency Risk**: Different implementations may diverge
+- **Wasted Effort**: Each dialect spends 3+ months reimplementing
+
+**Current Consumers**:
+- **CIR** (Clang IR): Needs C/C++ calling conventions
+- **FIR** (Fortran IR): Needs Fortran calling conventions
+- **Future dialects**: Will need similar functionality
+
+### Proposed Solution
+
+Create a **three-layer MLIR-agnostic framework**:
+
+1. **Layer 1**: Pure ABI classification logic (target-specific, ~95% reusable)
+2. **Layer 2**: Type/layout abstractions (dialect-agnostic interfaces)
+3. **Layer 3**: Dialect-specific operation rewriting
+
+**Key Insight**: We're refactoring existing, working code from the CIR incubator - not building from scratch. This significantly reduces risk and development time.
+
+---
+
+## Architecture Overview
+
+### Three-Layer Design
+
+```
+╔═══════════════════════════════════════════════════════╗
+║  Layer 1: Pure ABI Logic (Target-Specific)            ║
+║  ┌─────────────────────────────────────────────────┐  ║
+║  │ X86_64ABIInfo, AArch64ABIInfo                   │  ║
+║  │ Classification algorithms, register allocation  │  ║
+║  │ ~95% reusable across dialects                   │  ║
+║  └─────────────────────────────────────────────────┘  ║
+╚═══════════════════════════════════════════════════════╝
+                         ↓
+╔═══════════════════════════════════════════════════════╗
+║  Layer 2: Type/Layout Abstraction                     ║
+║  ┌─────────────────────────────────────────────────┐  ║
+║  │ ABITypeInterface (15-20 methods)                │  ║
+║  │ - Type queries: isRecord(), getNumFields()      │  ║
+║  │ - Size/alignment via DataLayoutInterface        │  ║
+║  │                                                 │  ║
+║  │ ABIArgInfo (classification result)              │  ║
+║  │ - Direct, Indirect, Extend, Expand, etc.        │  ║
+║  └─────────────────────────────────────────────────┘  ║
+╚═══════════════════════════════════════════════════════╝
+                         ↓
+╔═══════════════════════════════════════════════════════╗
+║  Layer 3: Dialect-Specific Rewriting                  ║
+║  ┌─────────────────────────────────────────────────┐  ║
+║  │ ABIRewriteContext (callbacks)                   │  ║
+║  │ - Operation creation (per-dialect)              │  ║
+║  │ - Value coercion, memory ops, aggregates        │  ║
+║  │                                                 │  ║
+║  │ Each dialect: 800-1,000 lines                   │  ║
+║  └─────────────────────────────────────────────────┘  ║
+╚═══════════════════════════════════════════════════════╝
+```
+
+### Directory Structure
+
+```
+mlir/
+├── include/mlir/Interfaces/
+│   └── ABITypeInterface.td           # Type query interface
+├── include/mlir/Target/ABI/
+│   ├── ABIArgInfo.h                  # Classification result
+│   ├── LowerFunctionInfo.h           # Function signature
+│   └── ABIRewriteContext.h           # Dialect callbacks
+└── lib/Target/ABI/
+    ├── ABIInfo.h/cpp                 # Base class
+    ├── TargetRegistry.h/cpp          # Target → ABI mapping
+    ├── X86/
+    │   └── X86_64ABIInfo.h/cpp       # x86_64 implementation
+    └── AArch64/
+        └── AArch64ABIInfo.h/cpp      # AArch64 implementation
+
+clang/lib/CIR/Dialect/Transforms/TargetLowering/
+├── CallConvLowering.cpp              # CIR-specific pass
+└── CIRABIRewriteContext.h/cpp        # CIR operation rewriting
+```
+
+### Key Components
+
+**From CIR Incubator** (70% done, needs refactoring):
+- `ABIArgInfo` (~500 lines) - fully reusable
+- `LowerFunctionInfo` (~300 lines) - fully reusable
+- `X86_64ABIInfo` (~2,000 lines) - needs interface adaptation
+- `AArch64ABIInfo` (~1,500 lines) - needs interface adaptation
+
+**New Infrastructure** (30% of work):
+- `ABITypeInterface` (15-20 methods) - TableGen definition
+- `ABIRewriteContext` (15-20 methods) - callback interface
+- `TargetRegistry` - maps target triples to ABI implementations
+
+---
+
+## Core Interfaces
+
+### ABITypeInterface
+
+**Purpose**: Dialect-agnostic type queries for ABI classification
+
+**TableGen Definition**:
+```tablegen
+def ABITypeInterface : TypeInterface<"ABITypeInterface"> {
+  let methods = [
+    // Basic type queries
+    InterfaceMethod<"Check if type is an integer",
+      "bool", "isInteger", (ins)>,
+    InterfaceMethod<"Check if type is a record (struct/class)",
+      "bool", "isRecord", (ins)>,
+    InterfaceMethod<"Check if type is floating point",
+      "bool", "isFloatingPoint", (ins)>,
+      
+    // Critical for classification
+    InterfaceMethod<"Get number of fields in record",
+      "unsigned", "getNumFields", (ins)>,
+    InterfaceMethod<"Get field type by index",
+      "mlir::Type", "getFieldType", (ins "unsigned", "$index")>,
+    InterfaceMethod<"Get field offset in bits",
+      "uint64_t", "getFieldOffsetInBits", 
+      (ins "unsigned", "$index", "mlir::DataLayout", "$layout")>,
+      
+    // Size/alignment (via DataLayoutInterface)
+    InterfaceMethod<"Get type size in bits",
+      "uint64_t", "getSizeInBits", (ins "mlir::DataLayout", "$layout")>,
+    InterfaceMethod<"Get ABI alignment in bits",
+      "uint32_t", "getABIAlignmentInBits", (ins "mlir::DataLayout", "$layout")>,
+      
+    // Edge cases
+    InterfaceMethod<"Check if type is __int128",
+      "bool", "isInt128", (ins)>,
+    InterfaceMethod<"Check if type is _BitInt(N)",
+      "bool", "isBitInt", (ins)>,
+  ];
+}
+```
+
+**Dialect Implementation Example**:
+```cpp
+// CIR
+class IntType : public Type<IntType, ..., ABITypeInterface::Trait> {
+  bool isInteger() { return true; }
+  bool isRecord() { return false; }
+  unsigned getNumFields() { return 0; }  // Not a record
+  // ... other methods
+};
+```
+
+**Per-Dialect Cost**: 800-1,000 lines to implement for all types
+
+### ABIArgInfo
+
+**Purpose**: Describes how a single argument or return value should be passed
+
+**Structure** (already exists in CIR, will be moved to shared location):
+```cpp
+class ABIArgInfo {
+  enum Kind {
+    Direct,          // Pass directly (possibly coerced)
+    Extend,          // Pass with sign/zero extension
+    Indirect,        // Pass via hidden pointer
+    Expand,          // Expand into constituent fields
+    Ignore,          // Ignore (empty struct/void)
+    CoerceAndExpand, // Coerce and expand
+  };
+  
+  mlir::Type CoerceToType;  // Target type for coercion
+  mlir::Type PaddingType;   // Padding type if needed
+  // Flags: InReg, CanBeFlattened, SignExt, etc.
+};
+```
+
+### ABIRewriteContext
+
+**Purpose**: Dialect-specific callbacks for operation rewriting
+
+**Interface**:
+```cpp
+class ABIRewriteContext {
+public:
+  virtual ~ABIRewriteContext() = default;
+  
+  // Operation creation
+  virtual Operation *createCall(
+      Location loc, Value callee, TypeRange results, ValueRange args) = 0;
+  
+  virtual Value createLoad(Location loc, Value ptr) = 0;
+  virtual void createStore(Location loc, Value value, Value ptr) = 0;
+  virtual Value createAlloca(Location loc, Type type, unsigned align) = 0;
+  
+  // Value coercion
+  virtual Value createBitcast(Location loc, Value value, Type targetType) = 0;
+  virtual Value createZExt(Location loc, Value value, Type targetType) = 0;
+  
+  // Aggregate operations
+  virtual Value createExtractValue(
+      Location loc, Value aggregate, ArrayRef<unsigned> indices) = 0;
+  virtual Value createInsertValue(
+      Location loc, Value aggregate, Value element, 
+      ArrayRef<unsigned> indices) = 0;
+};
+```
+
+**Dialect Implementation**:
+```cpp
+class CIRABIRewriteContext : public ABIRewriteContext {
+  OpBuilder &builder;
+  
+  Operation *createCall(...) override {
+    return builder.create<cir::CallOp>(...);
+  }
+  // ... other CIR-specific implementations
+};
+```
+
+---
+
+## Implementation Plan
+
+### Timeline: 17-19 Weeks (4-5 Months)
+
+#### Phase Breakdown
+
+| Phase | Duration | Cumulative | Deliverable |
+|-------|----------|------------|-------------|
+| **Phase 1**: Infrastructure Setup | 2 weeks | Weeks 1-2 | MLIR directory structure, interfaces defined |
+| **Phase 2**: CIR Integration | 2-2.5 weeks | Weeks 3-4.5 | CIR types implement ABITypeInterface |
+| **Phase 3**: Extract Target Logic | 3-3.5 weeks | Weeks 5-8 | X86_64, AArch64 in shared location |
+| **Phase 4**: CIR Lowering Pass | 3 weeks | Weeks 9-11 | CIR calling convention lowering working |
+| **Phase 5**: Testing & Validation | 2-3 weeks | Weeks 12-14 | 650+ tests, ABI compliance validated |
+| **Phase 6**: Varargs Support | 3-4 weeks | Weeks 15-18 | printf/scanf/varargs working |
+| **Phase 7**: Documentation | 1 week | Week 19 | API docs, user guides |
+
+#### Phase 1: Infrastructure Setup (Weeks 1-2)
+
+**Critical Week 2 Go/No-Go Decision**: Resolve TargetInfo dependency (see [Critical Decisions](#critical-decisions))
+
+1. Create directory structure in `mlir/include/mlir/Target/ABI/`
+2. Move `ABIArgInfo` from CIR to shared location
+3. Adapt `LowerFunctionInfo` for MLIR-agnostic use
+4. Define `ABITypeInterface` in TableGen
+5. Create `ABIRewriteContext` interface
+6. Set up build system
+
+**Week 1-2 Validation Tasks**:
+- Audit actual `TargetInfo` usage in CIR incubator
+- Measure CIR coupling depth (count `dyn_cast<cir::Type>` sites)
+- Prototype Option A (MLIR-native attributes) with x86_64
+- Ask Andy: Is varargs required for graduation?
+
+#### Phase 2: CIR Integration (Weeks 3-4.5)
+
+1. Implement `ABITypeInterface` for CIR types:
+   - `cir::IntType`, `cir::BoolType`
+   - `cir::RecordType` (15-20 methods including field iteration)
+   - `cir::PointerType`, `cir::ArrayType`
+   - `cir::FloatType`, `cir::DoubleType`
+2. Implement `CIRABIRewriteContext`
+3. Add unit tests for type queries
+
+#### Phase 3: Extract Target Logic (Weeks 5-8)
+
+1. Move `X86_64ABIInfo` from CIR to `mlir/lib/Target/ABI/X86/`
+2. Replace CIR type casts with `ABITypeInterface` queries
+   - Expected: 100-200 sites
+   - Risk: Could be 300-400 sites (+1 week)
+3. Move `AArch64ABIInfo` similarly
+4. Create `TargetRegistry`
+5. Add classification unit tests
+
+#### Phase 4: CIR Lowering Pass (Weeks 9-11)
+
+1. Create new `CallConvLowering` pass using shared infrastructure
+2. Implement function signature rewriting
+3. Implement call site rewriting
+4. Handle value coercion (Direct, Indirect, Expand)
+5. Add integration tests
+
+#### Phase 5: Testing & Validation (Weeks 12-14)
+
+**Test Coverage: 650+ tests**
+
+1. **Systematic Tests** (500+):
+   - **x86_64 System V** (250 tests):
+     - Basic types: int, float, __int128, _BitInt (20 tests)
+     - Structs: varying sizes/alignments (100 tests)
+     - Unions, arrays, edge cases (80 tests)
+     - Varargs: printf/scanf (30 tests, if implemented)
+   - **AArch64 PCS** (250 tests):
+     - Basic types (20 tests)
+     - HFA/HVA detection (80 tests - critical)
+     - Structs, over-alignment (80 tests)
+     - Edge cases (40 tests)
+
+2. **Differential Tests** (100+):
+   - Compare generated assembly vs classic Clang
+   - Real-world struct layouts
+
+3. **Interop Tests** (50+):
+   - Actual C→CIR→C function calls
+   - Runtime binary compatibility
+
+#### Phase 6: Varargs Support (Weeks 15-18)
+
+**Probability Required**: 70-80% (most C programs use printf/scanf)
+
+**Work Required**:
+
+1. **x86_64 System V** (1.5-2 weeks):
+   - Implement `va_list`, `va_start`, `va_arg`, `va_end`
+   - Handle register save area (168 bytes)
+   - Track GP vs FP registers separately
+   - 30+ tests
+
+2. **AArch64 PCS** (1.5-2 weeks):
+   - Different `va_list` structure
+   - Stack-based varargs
+   - 30+ tests
+
+#### Phase 7: Documentation (Week 19)
+
+1. API documentation
+2. User guide for adding new dialects
+3. Target implementation guide
+4. Design rationale
+
+### Resource Requirements
+
+**Engineering Time**:
+- Primary Developer: 1 FTE for 17-19 weeks
+- Code Reviews: 2-4 hours/week from 2 reviewers
+- FIR Collaboration: Week 4 check-in
+
+**Total Investment**: ~500 engineering hours (~$85-110K)
+
+**ROI**: Saves 2-3 months per additional dialect (~$100K+ each)
+
+---
+
+## Target ABI Details
+
+### x86_64 System V ABI
+
+**Reference**: [System V AMD64 ABI](https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf)
+
+**Key Rules**:
+- Integer arguments in registers: RDI, RSI, RDX, RCX, R8, R9
+- FP arguments in XMM0-XMM7
+- Return in RAX/RDX (integer) or XMM0/XMM1 (FP)
+- Structs classified by 8-byte chunks
+
+**Classification Algorithm**:
+1. Divide type into 8-byte chunks
+2. Classify each chunk (INTEGER, SSE, X87, MEMORY, NOCLASS)
+3. Merge adjacent chunks
+4. Post-merge cleanup
+5. Map to registers or memory
+
+**Critical Edge Case: `__int128` vs `_BitInt(128)`**
+
+These types have the same size (16 bytes) but **different ABI classification**:
+- `__int128`: **INTEGER** class → passed in RDI + RSI
+- `_BitInt(128)`: **MEMORY** class → passed indirectly via hidden pointer
+
+**Why This Matters**: Implementation must use `ABITypeInterface` methods `isInt128()` and `isBitInt()` to distinguish correctly.
+
+**Implementation Status**: ✅ Already implemented in CIR incubator
+
+### AArch64 Procedure Call Standard
+
+**Reference**: [ARM AArch64 ABI](https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst)
+
+**Key Rules**:
+- Integer arguments in X0-X7
+- FP arguments in V0-V7
+- Return in X0/X1 (integer) or V0/V1 (FP)
+- Homogeneous Floating-point Aggregates (HFA) in FP registers
+- Homogeneous Short-Vector Aggregates (HVA) in vector registers
+
+**Classification**:
+1. Check if type is HFA/HVA
+2. If aggregate, check if fits in registers
+3. Otherwise, pass indirectly
+
+**Implementation Status**: ✅ Already implemented in CIR incubator
+
+---
+
+## Critical Decisions
+
+### 1. TargetInfo Dependency ⚠️ **HIGH PRIORITY**
+
+**Issue**: Should MLIR-agnostic ABI code depend on `clang::TargetInfo`?
+
+**Context**: The CIR incubator uses `clang::TargetInfo` to query target properties (pointer width, alignment, etc.). This creates an MLIR→Clang dependency.
+
+#### Three Options
+
+| Option | Approach | Pros | Cons | Effort |
+|--------|----------|------|------|--------|
+| **A** | `llvm::Triple` + `DataLayoutInterface` + MLIR attributes | Clean layering, MLIR-idiomatic | Need to define ~10-15 attributes | 3-5 days |
+| **B** | Keep `clang::TargetInfo` | Zero effort, mature | **MLIR→Clang dependency violates principles** | 0 days |
+| **C** | Minimal `mlir::target::TargetInfo` | Clean layering | Duplicates Clang knowledge | 1-2 weeks |
+
+#### Recommendation: Option A (VERIFY THEN COMMIT)
+
+**Rationale**:
+- ✅ **MLIR Independence**: Maintains MLIR as peer to Clang
+- ✅ **Architectural Correctness**: TargetInfo is input/metadata, should be expressible in MLIR
+- ✅ **Reasonable Effort**: 3-5 days with clear path forward
+- ✅ **Upstream Acceptance**: MLIR maintainers will approve
+
+**Option A Approach**:
+```cpp
+// Instead of clang::TargetInfo, use:
+llvm::Triple triple;                      // From LLVM (arch/OS/vendor)
+mlir::DataLayoutSpecInterface layout;     // From MLIR (sizes/alignments)
+mlir::ModuleOp attributes;                // Target-specific properties
+
+// Example queries:
+unsigned ptrWidth = layout.getTypeSizeInBits(ptrType);
+bool isLittleEndian = triple.isLittleEndian();
+```
+
+**Why Not Option B**:
+- ❌ **Breaks MLIR Independence**: MLIR is peer to Clang, not dependent
+- ❌ **Upstream Rejection Risk**: MLIR maintainers will likely request MLIR-native approach
+- ⚠️ **False Economy**: Zero implementation time now, but redesign later if rejected
+
+**Decision Timeline**: **End of Week 2**
+
+**Week 2 Go/No-Go Criteria**:
+
+**🟢 GREEN (Proceed)**:
+- TargetInfo usage: ≤30 methods → Option A feasible
+- CIR coupling: ≤250 type cast sites
+- Total additional risk: ≤2 weeks
+
+**🟡 YELLOW (Proceed with Caution)**:
+- TargetInfo usage: 31-40 methods → Option A challenging
+- CIR coupling: 251-350 sites
+- Total additional risk: 2.5-4 weeks → 17-19 week timeline
+
+**🔴 RED (Pivot to Strategy 1)**:
+- TargetInfo usage: >40 methods → Option C required (+2 weeks)
+- CIR coupling: >350 sites (+2 weeks)
+- Total additional risk: >4 weeks → **Pivot to graduate with current implementation**
+
+### 2. Varargs Support ⚠️ **LIKELY REQUIRED**
+
+**Issue**: CIR incubator has many `NYI` assertions for varargs. Real-world C code (printf, scanf, logging) heavily uses varargs.
+
+**Assessment**:
+- **Probability Required**: 70-80% (most C programs use printf/scanf)
+- **Impact if Deferred**: ~40% of C code would be unusable
+- **Graduation Risk**: Reviewers may block graduation without varargs
+
+**Recommendation**: **Assume varargs IS required** and budget 17-19 weeks, not 15 weeks
+
+**Decision Timeline**: **Week 1** (ask Andy immediately during validation)
+
+### 3. FIR (Fortran) Coordination
+
+**Week 4 Check-In**: Validate ABITypeInterface/ABIRewriteContext for Fortran needs
+
+**Fortran-Specific Challenges**:
+
+1. **CHARACTER Types** (hidden length parameter):
+   - gfortran passes length AFTER all explicit args
+   - `foo(x, str, y)` → `foo(x, str_data, y, str_len)`
+   - Requires ABIRewriteContext extension for hidden arguments
+
+2. **Array Descriptors**:
+   - Fortran arrays have descriptors (bounds, strides, pointer)
+   - Need representation in ABITypeInterface
+
+**FIR Integration Estimate**: 1,000-1,200 lines (vs 800-1,000 for C-like dialects)
+
+---
+
+## Testing Strategy
+
+### ABI Compliance Tests (650+ total)
+
+#### 1. Systematic Tests (500+)
+
+**x86_64 System V** (250 tests):
+- Basic types: int, float, __int128, _BitInt (20 tests)
+- Structs: 1-byte, 2-byte, 4-byte, 8-byte, 9-byte, 16-byte (100 tests)
+- Unions: FP+integer, multiple FP, nested (30 tests)
+- Arrays: Fixed-size, multi-dimensional (20 tests)
+- Edge cases: empty structs, bitfields, over-aligned (50 tests)
+- Varargs: printf/scanf edge cases (30 tests)
+
+**AArch64 PCS** (250 tests):
+- Basic types (20 tests)
+- HFA/HVA detection: 1-5 fields, nested, mixed types (80 tests - **CRITICAL**)
+- Structs: various sizes and alignments (80 tests)
+- Over-alignment: 16, 32, 64-byte aligned (30 tests)
+- Edge cases: empty structs, padding (40 tests)
+
+#### 2. Differential Tests (100+)
+
+- Compare generated assembly vs classic Clang
+- Real-world struct layouts from open-source projects
+- Ensures ABI compliance
+
+#### 3. Interoperability Tests (50+)
+
+- Actual C→CIR→C function calls
+- Runtime binary compatibility verification
+
+### Performance Benchmarks
+
+**Compilation Time**:
+- Target: < 5% overhead (classic Clang ABI lowering adds ~1-2%)
+- Measurement: Profile on LLVM test-suite
+- Note: This is **compile-time** overhead, not runtime
+
+---
+
+## Success Metrics
+
+### Functional Metrics
+
+- ✅ CIR can lower x86_64 calling conventions (100% test pass)
+- ✅ CIR can lower AArch64 calling conventions (100% test pass)
+- ✅ ABI output matches classic Clang codegen
+- ✅ All CIR incubator tests pass with new implementation
+
+### Quality Metrics
+
+- ✅ Code coverage > 90% for ABI classification logic
+- ✅ Zero known ABI compliance bugs
+- ✅ Documentation complete
+
+### Performance Metrics
+
+- ✅ CallConvLowering pass overhead < 5% compilation time
+- ✅ No degradation in generated code quality
+
+### Reusability Metrics
+
+- ✅ FIR can adopt infrastructure with < 2 weeks integration effort
+- ✅ New target can be added with < 1 week effort
+- ✅ Per-dialect cost: 800-1,000 lines of code
+
+---
+
+## Multi-Dialect Support
+
+### Per-Dialect Integration Cost
+
+**CIR** (C-like dialects):
+- ABITypeInterface: 800-1,000 lines
+- ABIRewriteContext: 300-500 lines
+- **Total**: < 2 weeks engineering time
+
+**FIR** (Fortran-specific):
+- ABITypeInterface: 1,000-1,200 lines
+- CHARACTER hidden length handling
+- Array descriptor representation
+- **Total**: ~2-3 weeks engineering time
+
+### Benefits
+
+**For CIR**:
+- Correctness: Proven ABI compliance
+- Maintainability: Share updates with other dialects
+- Upstream Path: Clear acceptance path
+
+**For FIR**:
+- Reduced Effort: < 3 weeks vs 3 months from scratch
+- Correctness: Reuse battle-tested ABI logic
+- Interoperability: Guaranteed compatibility with C/C++ code
+
+**For LLVM Community**:
+- Code Reuse: Future dialects get calling convention support "for free"
+- Consistency: Single source of truth for ABI rules
+- Quality: Shared testing and validation
+
+---
+
+## Future Work
+
+### Additional Targets
+
+- RISC-V (emerging ISA)
+- WebAssembly (for web-based backends)
+- ARM32 (for embedded systems)
+- PowerPC (for HPC)
+
+### Advanced Features
+
+**Microsoft ABI**:
+- Windows calling conventions
+- MSVC C++ ABI
+- Estimated: 4-6 weeks
+
+**C++ Non-Trivial Types** (Phase 2):
+- Non-trivial copy constructors
+- Non-trivial destructors
+- Move-only types
+
+**Optimization Opportunities**:
+- Return Value Optimization (RVO)
+- Tail Call Optimization
+- Inlining-Aware Lowering
+
+### GSoC Integration
+
+**Monitor GSoC Progress**:
+- Track PR #140112 development
+- Assess fit with MLIR needs
+- Plan integration if beneficial
+
+**Timeline**:
+- Short term (Q1 2026): Implement MLIR-native solution
+- Medium term (Q2-Q3 2026): Evaluate GSoC library
+- Long term (Q4 2026+): Potentially refactor to use GSoC
+
+---
+
+## Risk Assessment
+
+| Risk | Probability | Impact | Mitigation |
+|------|-------------|--------|------------|
+| **TargetInfo dependency rejected** | Medium (30%) | High (+1-3 weeks) | Week 1-2 validation, Option A prototype ready |
+| **Varargs required for graduation** | High (70-80%) | High (+3-4 weeks) | Assume required, budget 17-19 weeks |
+| **CIR coupling deeper than expected** | Medium (30%) | Medium (+0.5-1 week) | Week 1 audit reveals actual coupling |
+| **Performance overhead > 5%** | Low | High | Profile early, optimize hot paths, caching |
+| **ABI compliance bugs** | Low | Critical | Extensive testing vs classic codegen |
+
+**Overall Risk**: **Medium** - Key architectural decision (TargetInfo) must be resolved in Week 2.
+
+---
+
+## References
+
+### ABI Specifications
+
+- [System V AMD64 ABI](https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf)
+- [ARM AArch64 PCS](https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst)
+- [Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html)
+
+### LLVM/MLIR Documentation
+
+- [MLIR Interfaces](https://mlir.llvm.org/docs/Interfaces/)
+- [MLIR Type System](https://mlir.llvm.org/docs/DefiningDialects/AttributesAndTypes/)
+- [MLIR Pass Infrastructure](https://mlir.llvm.org/docs/PassManagement/)
+
+### Related Projects
+
+- [GSoC ABI Lowering RFC](https://discourse.llvm.org/t/rfc-an-abi-lowering-library-for-llvm/84495)
+- [GSoC PR #140112](https://github.com/llvm/llvm-project/pull/140112)
+- [CIR Project](https://github.com/llvm/clangir)
+
+### Related Implementation
+
+- Clang CodeGen: `clang/lib/CodeGen/`
+- CIR Incubator: `clang/lib/CIR/Dialect/Transforms/TargetLowering/`
+
+---
+
+## Appendix: Glossary
+
+- **ABI**: Application Binary Interface
+- **CC**: Calling Convention
+- **CIR**: Clang Intermediate Representation (MLIR-based)
+- **FIR**: Fortran Intermediate Representation (MLIR-based)
+- **HFA**: Homogeneous Floating-point Aggregate (ARM term)
+- **HVA**: Homogeneous Short-Vector Aggregate (ARM term)
+- **NYI**: Not Yet Implemented
+- **PCS**: Procedure Call Standard (ARM term)
+
+---
+
+**Contact**: Adam Smith (CIR Team)  
+**Last Updated**: January 2026
+
+---
+
+*This design builds on the proven foundation of the CIR incubator implementation while extending it to be reusable by the broader MLIR ecosystem. Community feedback is welcomed and encouraged.*

>From 0084af3f133708f887e60b097a6782ff1b447196 Mon Sep 17 00:00:00 2001
From: Adam Smith <adams at nvidia.com>
Date: Tue, 27 Jan 2026 16:08:51 -0800
Subject: [PATCH 2/3] Fix technical errors and standardize paths in ClangIR ABI
 Lowering design
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- Correct register save area size from 168 to 176 bytes (6 GP × 8 + 8 FP × 16)
- Standardize code locations to follow MLIR conventions:
  - Cross-dialect interfaces: mlir/Interfaces/ABI/
  - Target-specific implementations: mlir/Target/ABI/
- Update architecture diagram and file structure appendix
---
 clang/docs/ClangIRABILowering.md | 1639 ++++++++++++++++++++++--------
 1 file changed, 1195 insertions(+), 444 deletions(-)

diff --git a/clang/docs/ClangIRABILowering.md b/clang/docs/ClangIRABILowering.md
index 7806a1a6d541c..3b9c08335c330 100644
--- a/clang/docs/ClangIRABILowering.md
+++ b/clang/docs/ClangIRABILowering.md
@@ -1,51 +1,66 @@
-# MLIR-Agnostic Calling Convention Lowering
+# ClangIR ABI Lowering - Design Document
 
 **Version**: 1.0  
 **Date**: January 2026  
 **Authors**: Adam Smith (CIR Team)  
-**Status**: Design Document - Ready for Community Review
+**Status**: Complete Specification - Ready for Implementation  
+**Target**: x86_64 and AArch64 (primary), extensible to other targets
 
 ---
 
-## Abstract
+## Quick Start: How to Read This Document
 
-Calling convention lowering (transforming function signatures to match target ABI requirements) is currently duplicated across MLIR dialects. This document proposes a three-layer MLIR-agnostic framework that enables code reuse while maintaining dialect independence.
+**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
 
-**Key Points**:
-- **Problem**: Each MLIR dialect reimplements ABI lowering from scratch
-- **Solution**: Refactor CIR's existing implementation (~7,000 lines, 70% complete) into reusable infrastructure
-- **Timeline**: 17-19 weeks (4-5 months)
-- **Benefits**: Future dialects can integrate in < 2 weeks vs 3 months from scratch
+---
 
-**Reading Guide**:
-- **5 minutes**: Read this Abstract and Architecture Overview
-- **30 minutes**: Add Implementation Plan and Critical Decisions
-- **2 hours**: Read entire document
+## 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
 
-## Table of Contents
+## I. Executive Summary
 
-1. [Background and Motivation](#background-and-motivation)
-2. [Architecture Overview](#architecture-overview)
-3. [Core Interfaces](#core-interfaces)
-4. [Implementation Plan](#implementation-plan)
-5. [Target ABI Details](#target-abi-details)
-6. [Critical Decisions](#critical-decisions)
-7. [Testing Strategy](#testing-strategy)
-8. [Success Metrics](#success-metrics)
-9. [References](#references)
+### 1.1 Problem Statement
+- Calling convention lowering is currently duplicated per-dialect
+- CIR incubator has partial implementation but CIR-specific
+- FIR and future dialects need similar functionality
+- Classic Clang codegen can't be reused directly (AST/LLVM IR specific)
 
----
+### 1.2 Proposed Solution
+Three-layer architecture:
+1. **Layer 1 (Dialect-Agnostic)**: Pure ABI classification logic
+2. **Layer 2 (Interface-Based)**: Type and layout abstractions
+3. **Layer 3 (Dialect-Specific)**: Operation rewriting per dialect
+
+### 1.3 Key Benefits
+- Avoids duplicating complex ABI logic across dialects
+- Maintains correct ABI compliance for all targets
+- Enables easier testing and validation
+- Provides migration path from CIR incubator
+
+### 1.4 Success Criteria
+- CIR can lower x86_64 and AArch64 calling conventions correctly
+- FIR can adopt the same infrastructure
+- Test suite validates ABI compliance
+- Performance overhead < 5% vs direct implementation
 
-## Background and Motivation
+## II. Background and Context
 
-### What is Calling Convention Lowering?
+### 2.1 What is Calling Convention Lowering?
 
-Calling convention lowering transforms high-level function signatures to match target ABI (Application Binary Interface) requirements.
+**Definition**: Transform high-level function signatures to match target ABI requirements.
 
 **Example** (x86_64 System V ABI):
-```mlir
+```cpp
 // High-level CIR
 func @foo(i32, struct<i64, i64>) -> i32
 
@@ -57,128 +72,265 @@ func @foo(i32 %arg0, i64 %arg1, i64 %arg2) -> i32
 //        +---- small integer passed in register
 ```
 
-### Current State
+### 2.2 Why It's Complex
+
+- **Target-specific**: Each architecture has different rules
+- **Type-dependent**: Rules differ for integers, floats, structs, unions, etc.
+- **Context-sensitive**: Varargs, virtual calls, special calling conventions
+- **ABI versions**: Same target may have multiple ABI variants
+
+### 2.3 Existing Implementations
+
+#### Classic Clang CodeGen
+- **Location**: `clang/lib/CodeGen/`
+- **Approach**: AST → LLVM IR during codegen
+- **Pros**: Mature, handles all targets, well-tested
+- **Cons**: Tightly coupled to Clang AST and LLVM IR
+
+#### CIR Incubator
+- **Location**: `clang/lib/CIR/Dialect/Transforms/TargetLowering/`
+- **Approach**: CIR ops → ABI-lowered CIR ops (MLIR pass)
+- **Pros**: Works with MLIR, adapted classic logic
+- **Cons**: CIR-specific types and operations
+
+#### GSoC ABI Lowering Library (WIP)
+- **Status**: PR #140112, not yet merged
+- **Approach**: Independent ABI type system, extracted from Clang
+- **Pros**: Frontend-agnostic, reusable
+- **Cons**: Still in development, Clang/LLVM IR focused
+
+### 2.4 Requirements for MLIR Dialects
+
+**CIR Needs**:
+- Lower C/C++ calling conventions correctly
+- Support x86_64 and AArch64 initially
+- Handle structs, unions, complex types
+- Support instance methods, virtual calls
+
+**FIR Needs** (future):
+- Lower Fortran calling conventions
+- Handle Fortran-specific types (complex, derived types)
+- Support Fortran calling semantics
+
+**Common Needs**:
+- Target ABI compliance
+- Efficient lowering (minimal overhead)
+- Extensibility for new targets
+- Testability and validation
+
+### 2.4.1 Fortran-Specific Considerations (FIR)
+
+**Context**: FIR team (NVIDIA Fortran frontend) will be a major consumer of this infrastructure. Fortran has unique type system features and ABI semantics that differ from C/C++.
+
+**Fortran Types**:
+
+1. **Derived Types** (Fortran's version of structs):
+   ```fortran
+   type :: MyType
+     integer :: field1
+     real :: field2
+     type(OtherType) :: field3  ! Nested derived type
+   end type
+   ```
+   - **Handling**: Similar to C structs; ABITypeInterface `getNumFields()`, `getFieldType()`, `getFieldOffsetInBits()` should work
+   - **Status**: ✅ Covered by existing design
+
+2. **COMPLEX Types**:
+   ```fortran
+   complex :: z  ! 2 floats (real part + imaginary part)
+   ```
+   - **Handling**: Struct of 2 floats; ABITypeInterface includes `isComplexType()` + `getComplexElementType()` methods
+   - **Status**: ✅ Added in interface design
+
+3. **CHARACTER Types** (with hidden length parameter):
+   ```fortran
+   subroutine foo(str)
+     character(len=*) :: str  ! str is passed + hidden length parameter
+   end subroutine
+   ```
+   - **Fortran ABI Quirk**: Character strings are passed with TWO arguments:
+     1. Pointer to string data (explicit)
+     2. Hidden length parameter (integer, passed AFTER all explicit args)
+   - **Example**: `foo(x, str, y)` → lowered to `foo(x, str_data, y, str_len)`
+   - **Challenge**: ABIRewriteContext must support hidden argument insertion at arbitrary positions
+   - **Status**: ⚠️ **Week 4 FIR check-in will design solution**
+
+4. **Arrays** (descriptor-based, not C-style):
+   ```fortran
+   real, dimension(:,:) :: matrix  ! Allocatable, rank-2
+   ```
+   - **Fortran Reality**: Arrays have **descriptors** (hidden metadata: bounds, strides, pointer to data)
+   - Descriptor is passed, not the array itself
+   - **Challenge**: How to represent descriptor in ABITypeInterface?
+   - **Options**: 
+     - A) Add descriptor-specific methods (`isDescriptorType()`, `getDescriptorElementType()`)
+     - B) Treat as opaque struct (don't expose internals to ABI classification)
+   - **Status**: ⚠️ **Week 4 FIR check-in will decide approach**
+
+**Fortran ABI Semantics**:
+
+1. **Default Pass-by-Reference**:
+   - C/C++: Small types passed by value, large types by pointer
+   - **Fortran**: EVERYTHING passed by reference (except `INTENT(IN) VALUE`)
+   ```fortran
+   subroutine foo(x)
+     integer :: x  ! Passed by REFERENCE (pointer to integer)
+   end subroutine
+   ```
+   - **Handling**: ABIArgInfo `Indirect` kind (already exists)
+   - **Status**: ✅ Should work (FIR classifies everything as `Indirect` by default)
+
+2. **CHARACTER Hidden Length Argument Reordering**:
+   - gfortran ABI: CHARACTER lengths passed AFTER all explicit args
+   - Requires non-trivial argument reordering
+   - **Requires**: ABIRewriteContext extension for hidden arguments
+   - **Status**: ⚠️ **Design TBD in Week 4**
+
+**FIR Integration Estimate**:
+- **Per-Dialect Cost**: 1,000-1,200 lines (vs 800-1,000 for dialects without hidden args)
+- **Why Higher**: CHARACTER + descriptor handling, type-bound procedures
+- **FIR Types to Implement**: 8-10 types (IntegerType, RealType, LogicalType, ComplexType, CharacterType, RecordType, SequenceType, BoxType, PointerType, ReferenceType)
+
+**Testing Challenges**:
+- **No "Classic Fortran Codegen" Baseline**: Unlike CIR (compare with classic Clang), FIR has no equivalent
+- **Validation Approach**: Differential testing against `gfortran` or `ifort`
+- **Test Coverage**: 50-100 Fortran-specific test cases (CHARACTER, arrays, derived types, COMPLEX, interop with C)
+
+**Week 4 Validation Will Determine**:
+- Feasibility of CHARACTER hidden length mechanism
+- Array descriptor representation approach
+- Whether ABITypeInterface/ABIRewriteContext need Fortran-specific extensions
+
+## III. Design Overview
+
+### 3.1 Architecture Diagram
 
-**Classic Clang CodeGen** (`clang/lib/CodeGen/`):
-- Mature implementation for all targets
-- **Limitation**: Tightly coupled to Clang AST and LLVM IR
+```
+┌──────────────────────────────────────────────────────────────┐
+│         MLIR ABI Lowering Infrastructure                     │
+│         mlir/include/mlir/Interfaces/ABI/                    │
+└──────────────────────────────────────────────────────────────┘
+                              │
+            ┌─────────────────┼─────────────────┐
+            │                 │                 │
+            ▼                 ▼                 ▼
+    ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
+    │ CIR Dialect  │  │ FIR Dialect  │  │   Future     │
+    │              │  │              │  │   Dialects   │
+    └──────────────┘  └──────────────┘  └──────────────┘
+         │                 │                 │
+         └─────────────────┴─────────────────┘
+                           │
+                           ▼
+               ┌───────────────────────┐
+               │  Target ABI Logic     │
+               │  X86, AArch64, etc.   │
+               └───────────────────────┘
+```
 
-**CIR Incubator** (`clang/lib/CIR/Dialect/Transforms/TargetLowering/`):
-- ~7,000 lines of code, 70% complete
-- Supports x86_64 and AArch64
-- **Limitation**: CIR-specific types and operations
+### 3.2 Three-Layer Design
 
-**GSoC ABI Lowering Library** (PR #140112):
-- Frontend-agnostic approach
-- **Status**: Work in progress, not yet merged
+**Layer 1: Pure ABI Classification**
+- Input: mlir::Type + metadata
+- Output: ABIArgInfo (how to pass)
+- No dialect knowledge
+- Target-specific algorithms
 
-### The Problem
+**Layer 2: Type/Layout Abstraction**
+- ABITypeInterface for type queries
+- DataLayoutInterface (MLIR standard)
+- ABIArgInfo, LowerFunctionInfo data structures
+- Target info access
 
-- **Code Duplication**: Every MLIR dialect must reimplement ABI logic
-- **Maintenance Burden**: ABI bugs must be fixed in multiple places
-- **Inconsistency Risk**: Different implementations may diverge
-- **Wasted Effort**: Each dialect spends 3+ months reimplementing
+**Layer 3: Dialect-Specific Rewriting**
+- ABIRewriteContext interface
+- Dialect implements operation creation
+- Pass infrastructure per dialect
+- Value coercion, temporary allocation
 
-**Current Consumers**:
-- **CIR** (Clang IR): Needs C/C++ calling conventions
-- **FIR** (Fortran IR): Needs Fortran calling conventions
-- **Future dialects**: Will need similar functionality
+### 3.3 Key Components
 
-### Proposed Solution
+1. **ABIArgInfo**: Classification result (Direct, Indirect, Expand, etc.)
+2. **LowerFunctionInfo**: Classified function signature
+3. **ABITypeInterface**: Type queries for ABI decisions
+4. **ABIInfo**: Target-specific classification logic
+5. **ABIRewriteContext**: Dialect-specific operation rewriting
+6. **TargetRegistry**: Maps target triple to ABI implementation
 
-Create a **three-layer MLIR-agnostic framework**:
+## IV. Detailed Component Design
 
-1. **Layer 1**: Pure ABI classification logic (target-specific, ~95% reusable)
-2. **Layer 2**: Type/layout abstractions (dialect-agnostic interfaces)
-3. **Layer 3**: Dialect-specific operation rewriting
+### 4.1 ABIArgInfo (Already Exists in CIR)
 
-**Key Insight**: We're refactoring existing, working code from the CIR incubator - not building from scratch. This significantly reduces risk and development time.
+**Location**: `mlir/include/mlir/Interfaces/ABI/ABIArgInfo.h`
 
----
+**Purpose**: Describes how a single argument or return value should be passed.
 
-## Architecture Overview
+**Structure**:
+```cpp
+class ABIArgInfo {
+  enum Kind {
+    Direct,          // Pass directly (possibly coerced)
+    Extend,          // Pass with sign/zero extension
+    Indirect,        // Pass via hidden pointer
+    IndirectAliased, // Pass indirectly, may alias
+    Ignore,          // Ignore (empty struct/void)
+    Expand,          // Expand into constituent fields
+    CoerceAndExpand, // Coerce and expand
+    InAlloca         // Windows inalloca
+  };
+  
+  mlir::Type CoerceToType;  // Target type for coercion
+  mlir::Type PaddingType;   // Padding type if needed
+  // Flags: InReg, CanBeFlattened, SignExt, etc.
+};
+```
 
-### Three-Layer Design
+**Status**: ✅ Exists in CIR, already dialect-agnostic, just needs to be moved.
 
-```
-╔═══════════════════════════════════════════════════════╗
-║  Layer 1: Pure ABI Logic (Target-Specific)            ║
-║  ┌─────────────────────────────────────────────────┐  ║
-║  │ X86_64ABIInfo, AArch64ABIInfo                   │  ║
-║  │ Classification algorithms, register allocation  │  ║
-║  │ ~95% reusable across dialects                   │  ║
-║  └─────────────────────────────────────────────────┘  ║
-╚═══════════════════════════════════════════════════════╝
-                         ↓
-╔═══════════════════════════════════════════════════════╗
-║  Layer 2: Type/Layout Abstraction                     ║
-║  ┌─────────────────────────────────────────────────┐  ║
-║  │ ABITypeInterface (15-20 methods)                │  ║
-║  │ - Type queries: isRecord(), getNumFields()      │  ║
-║  │ - Size/alignment via DataLayoutInterface        │  ║
-║  │                                                 │  ║
-║  │ ABIArgInfo (classification result)              │  ║
-║  │ - Direct, Indirect, Extend, Expand, etc.        │  ║
-║  └─────────────────────────────────────────────────┘  ║
-╚═══════════════════════════════════════════════════════╝
-                         ↓
-╔═══════════════════════════════════════════════════════╗
-║  Layer 3: Dialect-Specific Rewriting                  ║
-║  ┌─────────────────────────────────────────────────┐  ║
-║  │ ABIRewriteContext (callbacks)                   │  ║
-║  │ - Operation creation (per-dialect)              │  ║
-║  │ - Value coercion, memory ops, aggregates        │  ║
-║  │                                                 │  ║
-║  │ Each dialect: 800-1,000 lines                   │  ║
-║  └─────────────────────────────────────────────────┘  ║
-╚═══════════════════════════════════════════════════════╝
-```
+### 4.2 LowerFunctionInfo
 
-### Directory Structure
+**Location**: `mlir/include/mlir/Interfaces/ABI/LowerFunctionInfo.h`
 
-```
-mlir/
-├── include/mlir/Interfaces/
-│   └── ABITypeInterface.td           # Type query interface
-├── include/mlir/Target/ABI/
-│   ├── ABIArgInfo.h                  # Classification result
-│   ├── LowerFunctionInfo.h           # Function signature
-│   └── ABIRewriteContext.h           # Dialect callbacks
-└── lib/Target/ABI/
-    ├── ABIInfo.h/cpp                 # Base class
-    ├── TargetRegistry.h/cpp          # Target → ABI mapping
-    ├── X86/
-    │   └── X86_64ABIInfo.h/cpp       # x86_64 implementation
-    └── AArch64/
-        └── AArch64ABIInfo.h/cpp      # AArch64 implementation
+**Purpose**: Represents function signature with ABI classification for each argument/return.
 
-clang/lib/CIR/Dialect/Transforms/TargetLowering/
-├── CallConvLowering.cpp              # CIR-specific pass
-└── CIRABIRewriteContext.h/cpp        # CIR operation rewriting
+**Structure**:
+```cpp
+class LowerFunctionInfo {
+  struct ArgInfo {
+    mlir::Type originalType;
+    ABIArgInfo abiInfo;
+  };
+  
+  unsigned CallingConvention;
+  unsigned EffectiveCallingConvention;
+  RequiredArgs Required;  // For varargs
+  
+  // Return type at index 0, args follow
+  SmallVector<ArgInfo> Args;
+};
 ```
 
-### Key Components
+**Methods**:
+```cpp
+ABIArgInfo &getReturnInfo();
+mlir::Type getReturnType();
+unsigned getNumArgs();
+ABIArgInfo &getArgInfo(unsigned i);
+mlir::Type getArgType(unsigned i);
+```
 
-**From CIR Incubator** (70% done, needs refactoring):
-- `ABIArgInfo` (~500 lines) - fully reusable
-- `LowerFunctionInfo` (~300 lines) - fully reusable
-- `X86_64ABIInfo` (~2,000 lines) - needs interface adaptation
-- `AArch64ABIInfo` (~1,500 lines) - needs interface adaptation
+**Status**: 🔄 Exists in CIR, needs minor adaptation for MLIR-agnostic use.
 
-**New Infrastructure** (30% of work):
-- `ABITypeInterface` (15-20 methods) - TableGen definition
-- `ABIRewriteContext` (15-20 methods) - callback interface
-- `TargetRegistry` - maps target triples to ABI implementations
+### 4.3 ABITypeInterface
 
----
+**Location**: `mlir/include/mlir/Interfaces/ABI/ABITypeInterface.td`
 
-## Core Interfaces
+**Purpose**: Provides type queries needed for ABI classification.
 
-### ABITypeInterface
+**Interface Definition** (TableGen):
 
-**Purpose**: Dialect-agnostic type queries for ABI classification
+> **TableGen Syntax Note**: `InterfaceMethod<description, return_type, method_name, parameters>` defines a polymorphic method that types can implement. `(ins)` means no parameters. This generates C++ virtual methods that each type overrides.
 
-**TableGen Definition**:
 ```tablegen
 def ABITypeInterface : TypeInterface<"ABITypeInterface"> {
   let methods = [
@@ -187,10 +339,28 @@ def ABITypeInterface : TypeInterface<"ABITypeInterface"> {
       "bool", "isInteger", (ins)>,
     InterfaceMethod<"Check if type is a record (struct/class)",
       "bool", "isRecord", (ins)>,
+    InterfaceMethod<"Check if type is a pointer",
+      "bool", "isPointer", (ins)>,
     InterfaceMethod<"Check if type is floating point",
       "bool", "isFloatingPoint", (ins)>,
+    InterfaceMethod<"Check if type is an array",
+      "bool", "isArray", (ins)>,
       
-    // Critical for classification
+    // Type navigation
+    InterfaceMethod<"Get pointee type for pointers",
+      "mlir::Type", "getPointeeType", (ins)>,
+    InterfaceMethod<"Get element type for arrays",
+      "mlir::Type", "getElementType", (ins)>,
+      
+    // Size and alignment queries
+    InterfaceMethod<"Get type size in bits",
+      "uint64_t", "getSizeInBits", (ins "mlir::DataLayout", "$layout")>,
+    InterfaceMethod<"Get ABI alignment in bits",
+      "uint32_t", "getABIAlignmentInBits", (ins "mlir::DataLayout", "$layout")>,
+    InterfaceMethod<"Get preferred alignment in bits",
+      "uint32_t", "getPreferredAlignmentInBits", (ins "mlir::DataLayout", "$layout")>,
+      
+    // Record (struct/class) queries - CRITICAL FOR ABI CLASSIFICATION
     InterfaceMethod<"Get number of fields in record",
       "unsigned", "getNumFields", (ins)>,
     InterfaceMethod<"Get field type by index",
@@ -198,60 +368,139 @@ def ABITypeInterface : TypeInterface<"ABITypeInterface"> {
     InterfaceMethod<"Get field offset in bits",
       "uint64_t", "getFieldOffsetInBits", 
       (ins "unsigned", "$index", "mlir::DataLayout", "$layout")>,
+    InterfaceMethod<"Check if record is empty (no fields)",
+      "bool", "isEmpty", (ins)>,
       
-    // Size/alignment (via DataLayoutInterface)
-    InterfaceMethod<"Get type size in bits",
-      "uint64_t", "getSizeInBits", (ins "mlir::DataLayout", "$layout")>,
-    InterfaceMethod<"Get ABI alignment in bits",
-      "uint32_t", "getABIAlignmentInBits", (ins "mlir::DataLayout", "$layout")>,
-      
-    // Edge cases
+    // Additional methods for ABI decisions
+    InterfaceMethod<"Check if integer type is signed",
+      "bool", "isSignedInteger", (ins)>,
+    InterfaceMethod<"Get integer width in bits",
+      "unsigned", "getIntegerBitWidth", (ins)>,
+    
+    // Additional methods that may be needed for edge cases (15-25 total)
+    InterfaceMethod<"Check if type is a union",
+      "bool", "isUnion", (ins)>,
+    InterfaceMethod<"Check if type is complex",
+      "bool", "isComplexType", (ins)>,
+    InterfaceMethod<"Get complex element type",
+      "mlir::Type", "getComplexElementType", (ins)>,
+    
+    // x86_64-specific edge cases (CRITICAL for ABI correctness)
     InterfaceMethod<"Check if type is __int128",
       "bool", "isInt128", (ins)>,
     InterfaceMethod<"Check if type is _BitInt(N)",
       "bool", "isBitInt", (ins)>,
+    InterfaceMethod<"Get _BitInt width",
+      "unsigned", "getBitIntWidth", (ins)>,
+    
+    // C++ ABI support (required if targeting C++)
+    InterfaceMethod<"Has non-trivial copy constructor",
+      "bool", "hasNonTrivialCopyCtor", (ins)>,
+    InterfaceMethod<"Has non-trivial destructor",
+      "bool", "hasNonTrivialDtor", (ins)>,
+    InterfaceMethod<"Check if type is trivially copyable",
+      "bool", "isTriviallyCopyable", (ins)>,
+    InterfaceMethod<"Check if type is vector",
+      "bool", "isVectorType", (ins)>,
+    InterfaceMethod<"Get vector element count",
+      "unsigned", "getVectorNumElements", (ins)>,
   ];
+  
+  let description = [{
+    Interface for types to provide ABI-relevant information.
+    
+    Key Design Notes:
+    - Field iteration (getNumFields, getFieldType, getFieldOffsetInBits) is 
+      CRITICAL for struct classification in x86_64 and AArch64 ABIs
+    - DataLayout is passed to size/alignment queries to support target-specific layouts
+    - Not all types implement all methods (e.g., integers don't have fields)
+    
+    **Method Count**: 15-20 methods shown, potentially 20-25 with edge cases
+    
+    **Additional Methods That May Be Needed**:
+    - Union handling (isUnion, getActiveUnionMember)
+    - Complex types (isComplexType, getComplexElementType) - shown above
+    - Vector types (isVectorType, getVectorNumElements) - shown above
+    - Flexible array members (isVariablySized)
+    - Padding queries (hasPaddingBetweenFields)
+    
+    **Week 1 Task**: Audit x86_64/AArch64 classification code to determine exact method list
+  }];
 }
 ```
 
-**Dialect Implementation Example**:
+**Dialects Implement**:
 ```cpp
 // CIR
 class IntType : public Type<IntType, ..., ABITypeInterface::Trait> {
   bool isInteger() { return true; }
   bool isRecord() { return false; }
-  unsigned getNumFields() { return 0; }  // Not a record
-  // ... other methods
+  // ...
+};
+
+// FIR
+class fir::IntType : public Type<fir::IntType, ..., ABITypeInterface::Trait> {
+  bool isInteger() { return true; }
+  // ...
 };
 ```
 
-**Per-Dialect Cost**: 800-1,000 lines to implement for all types
+**Status**: ✨ New, needs to be created.
+
+### 4.4 ABIInfo Base Class
 
-### ABIArgInfo
+**Location**: `mlir/lib/Target/ABI/ABIInfo.h`
 
-**Purpose**: Describes how a single argument or return value should be passed
+**Purpose**: Abstract base for target-specific ABI classification.
 
-**Structure** (already exists in CIR, will be moved to shared location):
+**Structure**:
 ```cpp
-class ABIArgInfo {
-  enum Kind {
-    Direct,          // Pass directly (possibly coerced)
-    Extend,          // Pass with sign/zero extension
-    Indirect,        // Pass via hidden pointer
-    Expand,          // Expand into constituent fields
-    Ignore,          // Ignore (empty struct/void)
-    CoerceAndExpand, // Coerce and expand
-  };
+class ABIInfo {
+protected:
+  const clang::TargetInfo &Target;
   
-  mlir::Type CoerceToType;  // Target type for coercion
-  mlir::Type PaddingType;   // Padding type if needed
-  // Flags: InReg, CanBeFlattened, SignExt, etc.
+public:
+  explicit ABIInfo(const clang::TargetInfo &Target);
+  virtual ~ABIInfo();
+  
+  // Pure virtual - must implement per target
+  virtual void computeInfo(LowerFunctionInfo &FI) const = 0;
+  
+  // Helpers
+  ABIArgInfo getNaturalAlignIndirect(mlir::Type Ty, mlir::DataLayout &DL);
+  bool isPromotableIntegerTypeForABI(mlir::Type Ty);
 };
 ```
 
-### ABIRewriteContext
+**Status**: 🔄 Exists in CIR, needs adaptation to remove CIR-specific dependencies.
+
+### 4.5 Target-Specific ABIInfo Implementations
+
+**Location**: `mlir/lib/Target/ABI/X86/`, `mlir/lib/Target/ABI/AArch64/`
+
+**Example: X86_64ABIInfo**:
+```cpp
+class X86_64ABIInfo : public ABIInfo {
+  enum Class { Integer, SSE, SSEUp, X87, X87Up, NoClass, Memory };
+  
+  void classify(mlir::Type Ty, uint64_t offset, Class &Lo, Class &Hi);
+  Class merge(Class A, Class B);
+  
+public:
+  ABIArgInfo classifyReturnType(mlir::Type Ty);
+  ABIArgInfo classifyArgumentType(mlir::Type Ty, ...);
+  
+  void computeInfo(LowerFunctionInfo &FI) const override;
+};
+```
+
+**Status**: 🔄 Exists in CIR, needs minor adaptation (remove CIR type casts, use ABITypeInterface).
+
+### 4.6 ABIRewriteContext Interface
 
-**Purpose**: Dialect-specific callbacks for operation rewriting
+**Location**: `mlir/include/mlir/Interfaces/ABI/ABIRewriteContext.h`
+
+**Purpose**: Dialect-specific callbacks for operation rewriting.
 
 **Interface**:
 ```cpp
@@ -260,165 +509,311 @@ public:
   virtual ~ABIRewriteContext() = default;
   
   // Operation creation
+  virtual Operation *createFunction(
+      Location loc, StringRef name, FunctionType type) = 0;
+  
   virtual Operation *createCall(
       Location loc, Value callee, TypeRange results, ValueRange args) = 0;
   
+  virtual Value createCast(
+      Location loc, Value value, Type targetType) = 0;
+  
   virtual Value createLoad(Location loc, Value ptr) = 0;
   virtual void createStore(Location loc, Value value, Value ptr) = 0;
+  
   virtual Value createAlloca(Location loc, Type type, unsigned align) = 0;
   
-  // Value coercion
-  virtual Value createBitcast(Location loc, Value value, Type targetType) = 0;
-  virtual Value createZExt(Location loc, Value value, Type targetType) = 0;
+  // Value coercion (CRITICAL for ABI lowering)
+  virtual Value createBitcast(
+      Location loc, Value value, Type targetType) = 0;
+  
+  virtual Value createTrunc(
+      Location loc, Value value, Type targetType) = 0;
   
-  // Aggregate operations
+  virtual Value createZExt(
+      Location loc, Value value, Type targetType) = 0;
+  
+  virtual Value createSExt(
+      Location loc, Value value, Type targetType) = 0;
+  
+  // Aggregate operations (CRITICAL for struct expansion)
   virtual Value createExtractValue(
       Location loc, Value aggregate, ArrayRef<unsigned> indices) = 0;
+  
   virtual Value createInsertValue(
       Location loc, Value aggregate, Value element, 
       ArrayRef<unsigned> indices) = 0;
+  
+  virtual Value createGEP(
+      Location loc, Value ptr, ArrayRef<Value> indices) = 0;
+  
+  // Type conversion
+  virtual FunctionType createFunctionType(
+      ArrayRef<Type> inputs, ArrayRef<Type> results) = 0;
+  
+  // Operation replacement
+  virtual void replaceOp(Operation *old, Operation *new_op) = 0;
 };
 ```
 
-**Dialect Implementation**:
+**Implementation Complexity**: **HIGH**
+- 15-20 methods total (not just 5-6 shown in original design)
+- Each dialect must implement all methods
+- Per-dialect cost: ~800-1000 lines (revised from 500)
+
+**Dialect Implements**:
 ```cpp
 class CIRABIRewriteContext : public ABIRewriteContext {
   OpBuilder &builder;
   
-  Operation *createCall(...) override {
-    return builder.create<cir::CallOp>(...);
+  Operation *createFunction(...) override {
+    return builder.create<cir::FuncOp>(...);
   }
   // ... other CIR-specific implementations
 };
 ```
 
----
-
-## Implementation Plan
+**Status**: ✨ New, needs to be created.
 
-### Timeline: 17-19 Weeks (4-5 Months)
+### 4.7 Target Registry
 
-#### Phase Breakdown
+**Location**: `mlir/lib/Target/ABI/TargetRegistry.h`
 
-| Phase | Duration | Cumulative | Deliverable |
-|-------|----------|------------|-------------|
-| **Phase 1**: Infrastructure Setup | 2 weeks | Weeks 1-2 | MLIR directory structure, interfaces defined |
-| **Phase 2**: CIR Integration | 2-2.5 weeks | Weeks 3-4.5 | CIR types implement ABITypeInterface |
-| **Phase 3**: Extract Target Logic | 3-3.5 weeks | Weeks 5-8 | X86_64, AArch64 in shared location |
-| **Phase 4**: CIR Lowering Pass | 3 weeks | Weeks 9-11 | CIR calling convention lowering working |
-| **Phase 5**: Testing & Validation | 2-3 weeks | Weeks 12-14 | 650+ tests, ABI compliance validated |
-| **Phase 6**: Varargs Support | 3-4 weeks | Weeks 15-18 | printf/scanf/varargs working |
-| **Phase 7**: Documentation | 1 week | Week 19 | API docs, user guides |
+**Purpose**: Map target triple to ABIInfo implementation.
 
-#### Phase 1: Infrastructure Setup (Weeks 1-2)
+**Interface**:
+```cpp
+class TargetABIRegistry {
+public:
+  static std::unique_ptr<ABIInfo> createABIInfo(
+      const llvm::Triple &triple,
+      const clang::TargetInfo &targetInfo);
+  
+private:
+  // Factory functions
+  static std::unique_ptr<ABIInfo> createX86_64ABIInfo(...);
+  static std::unique_ptr<ABIInfo> createAArch64ABIInfo(...);
+};
+```
 
-**Critical Week 2 Go/No-Go Decision**: Resolve TargetInfo dependency (see [Critical Decisions](#critical-decisions))
+**Implementation**:
+```cpp
+std::unique_ptr<ABIInfo> TargetABIRegistry::createABIInfo(
+    const llvm::Triple &triple,
+    const clang::TargetInfo &targetInfo) {
+  
+  switch (triple.getArch()) {
+  case llvm::Triple::x86_64:
+    return createX86_64ABIInfo(targetInfo);
+  case llvm::Triple::aarch64:
+    return createAArch64ABIInfo(targetInfo);
+  default:
+    return nullptr;  // Unsupported target
+  }
+}
+```
 
-1. Create directory structure in `mlir/include/mlir/Target/ABI/`
-2. Move `ABIArgInfo` from CIR to shared location
-3. Adapt `LowerFunctionInfo` for MLIR-agnostic use
-4. Define `ABITypeInterface` in TableGen
-5. Create `ABIRewriteContext` interface
-6. Set up build system
+**Status**: ✨ New, straightforward to create.
 
-**Week 1-2 Validation Tasks**:
-- Audit actual `TargetInfo` usage in CIR incubator
-- Measure CIR coupling depth (count `dyn_cast<cir::Type>` sites)
-- Prototype Option A (MLIR-native attributes) with x86_64
-- Ask Andy: Is varargs required for graduation?
+## V. Implementation Phases
 
-#### Phase 2: CIR Integration (Weeks 3-4.5)
+### Implementation Timeline & Risk Assessment
 
-1. Implement `ABITypeInterface` for CIR types:
-   - `cir::IntType`, `cir::BoolType`
-   - `cir::RecordType` (15-20 methods including field iteration)
-   - `cir::PointerType`, `cir::ArrayType`
-   - `cir::FloatType`, `cir::DoubleType`
-2. Implement `CIRABIRewriteContext`
-3. Add unit tests for type queries
+**Baseline Timeline**: 13 weeks (aggressive)  
+**Realistic Timeline**: 15 weeks (with contingency)  
+**With Varargs**: 17 weeks (if required for graduation)
 
-#### Phase 3: Extract Target Logic (Weeks 5-8)
+**Risk Factors**:
+1. CIR coupling depth: 100-200 type cast sites expected, could be 300-400 (+0.5-1 week)
+2. ABITypeInterface complexity: 15-20 methods with field iteration (+0.5 week)
+3. ABIRewriteContext complexity: 15-20 methods needed vs 5-6 shown (+0.5 week)
+4. Testing infrastructure: Differential testing setup takes time (+1 week)
 
-1. Move `X86_64ABIInfo` from CIR to `mlir/lib/Target/ABI/X86/`
-2. Replace CIR type casts with `ABITypeInterface` queries
-   - Expected: 100-200 sites
-   - Risk: Could be 300-400 sites (+1 week)
-3. Move `AArch64ABIInfo` similarly
-4. Create `TargetRegistry`
-5. Add classification unit tests
+**Contingency Recommendation**: Budget 15-16 weeks (20% buffer over 13 week baseline)
 
-#### Phase 4: CIR Lowering Pass (Weeks 9-11)
+---
 
-1. Create new `CallConvLowering` pass using shared infrastructure
+### Phase 1: Infrastructure Setup (Weeks 1-2)
+1. Create directory structure in `mlir/include/mlir/Interfaces/ABI/` and `mlir/include/mlir/Target/ABI/`
+2. Move ABIArgInfo from CIR to shared location
+3. Adapt LowerFunctionInfo for MLIR-agnostic use
+4. Define ABITypeInterface in TableGen
+5. Create ABIRewriteContext interface
+6. Set up build system (CMakeLists.txt)
+
+**Deliverable**: Compiling but empty infrastructure
+
+### Phase 2: CIR Integration - Type Interface (Weeks 3-4)
+1. Implement ABITypeInterface for CIR types
+   - cir::IntType, cir::BoolType
+   - cir::RecordType
+   - cir::PointerType
+   - cir::ArrayType
+   - cir::FuncType
+   - cir::FloatType, cir::DoubleType
+2. Test type queries
+3. Implement CIRABIRewriteContext
+
+**Deliverable**: CIR types implement ABITypeInterface
+
+**Implementation Notes**:
+- Must implement 15-20 methods per type (not just basic queries)
+- Field iteration for RecordType is critical and potentially complex
+- Estimated 1.5-2 weeks (upper end of range due to interface complexity)
+
+### Phase 3: Extract Target ABI Logic (Weeks 5-7)
+1. Move X86_64ABIInfo from CIR to `mlir/lib/Target/ABI/X86/`
+2. Replace CIR type casts with ABITypeInterface queries
+3. Move AArch64ABIInfo similarly
+4. Create TargetABIRegistry
+5. Add unit tests for classification
+
+**Deliverable**: Target ABI logic is MLIR-agnostic
+
+**Implementation Notes**:
+- Expected: 100-200 `dyn_cast<cir::Type>` replacement sites
+- Risk: Could be 300-400 sites if coupling deeper than expected
+- Each site must be refactored to use ABITypeInterface
+- Estimated 3-3.5 weeks (upper end if coupling is deeper)
+
+### Phase 4: CIR Calling Convention Pass (Weeks 8-10)
+1. Create new CallConvLowering pass using shared infrastructure
 2. Implement function signature rewriting
 3. Implement call site rewriting
-4. Handle value coercion (Direct, Indirect, Expand)
+4. Handle value coercion (direct, indirect, expand)
 5. Add integration tests
 
-#### Phase 5: Testing & Validation (Weeks 12-14)
+**Deliverable**: CIR can lower calling conventions using shared infrastructure
+
+### Phase 5: Testing and Validation (Weeks 11-12)
+
+**Duration**: 2-3 weeks
+
+**Testing Strategy Definition**:
+
+1. **Differential Testing** (1 week setup + ongoing):
+   - Create harness to compare CIR output with classic Clang codegen
+   - Assembly-level comparison for ABI compliance
+   - Automated regression detection
+
+2. **ABI Compliance Tests** (1 week):
+   - Port existing ABI test suites (x86_64 System V, AArch64 PCS)
+   - Create **500+ systematic test cases** covering:
+     - **x86_64 System V** (250+ tests):
+       - Basic types: int, float, pointer, __int128, _BitInt(20 tests)
+       - Structs: 1-byte, 2-byte, 4-byte, 8-byte, 9-byte, 16-byte (varying sizes/alignments) (100 tests)
+       - Unions: FP+integer, multiple FP, nested unions (30 tests)
+       - Arrays: Fixed-size, multi-dimensional (20 tests)
+       - Edge cases: empty structs, __int128 vs _BitInt, bitfields, over-aligned (50 tests)
+       - Varargs: printf/scanf edge cases (30 tests, if varargs implemented)
+     - **AArch64 PCS** (250+ tests):
+       - Basic types (20 tests)
+       - HFA/HVA detection: 1-5 fields, nested, mixed types (80 tests - CRITICAL)
+       - Structs: various sizes and alignments (80 tests)
+       - Over-alignment: 16, 32, 64-byte aligned structs (30 tests)
+       - Edge cases: empty structs, padding (40 tests)
+   - **Differential Tests** (100+ tests):
+     - Real-world struct layouts from open-source projects
+     - Compare assembly output with classic Clang
+   - **Interop Tests** (50+ tests):
+     - Actual C→CIR→C function calls
+     - Runtime binary compatibility verification
+
+3. **Performance Benchmarks** (3-5 days):
+   - Compilation time overhead measurement
+   - Generated code quality comparison
+   - 10-20 representative benchmarks
+
+4. **C++ Non-Trivial Types Testing** (Phase 2 only, 20 tests):
+   - Copy constructors (passed by value → call copy constructor)
+   - Destructors (temporary destruction)
+   - Deleted copy constructors (must pass by reference)
+   - Move-only types (std::unique_ptr, etc.)
+   - Note: Phase 1 is C-only; this testing applies to Phase 2 C++ support
+
+5. **Bug Fixing & Iteration** (1-2 weeks):
+   - Fix issues discovered by tests
+   - Handle edge cases
+   - Performance optimization if needed
+
+**Deliverable**: Production-ready CIR calling convention lowering
+
+**Implementation Notes**:
+- Testing infrastructure setup (differential testing harness) takes significant time (~1 week)
+- If infrastructure setup exceeds 1 week, may extend Phase 5 duration
+- Estimated 2-3 weeks (upper end due to testing infrastructure complexity)
+
+### Phase 6: Varargs Support (Conditional - If Required for Graduation)
+
+**Duration**: 3-4 weeks (not currently in baseline)
+
+**Probability Required**: **70-80%** (most C programs use `printf`/`scanf`)
 
-**Test Coverage: 650+ tests**
-
-1. **Systematic Tests** (500+):
-   - **x86_64 System V** (250 tests):
-     - Basic types: int, float, __int128, _BitInt (20 tests)
-     - Structs: varying sizes/alignments (100 tests)
-     - Unions, arrays, edge cases (80 tests)
-     - Varargs: printf/scanf (30 tests, if implemented)
-   - **AArch64 PCS** (250 tests):
-     - Basic types (20 tests)
-     - HFA/HVA detection (80 tests - critical)
-     - Structs, over-alignment (80 tests)
-     - Edge cases (40 tests)
-
-2. **Differential Tests** (100+):
-   - Compare generated assembly vs classic Clang
-   - Real-world struct layouts
-
-3. **Interop Tests** (50+):
-   - Actual C→CIR→C function calls
-   - Runtime binary compatibility
-
-#### Phase 6: Varargs Support (Weeks 15-18)
-
-**Probability Required**: 70-80% (most C programs use printf/scanf)
+**Rationale**:
+- CIR incubator has many `NYI` assertions for varargs
+- Real-world C code heavily uses varargs (printf, scanf, logging)
+- ~40% of C code would be unusable without varargs support
+- Graduation reviewers may block without varargs
+- Complex state management (GP vs FP register tracking, register save area, 30+ tests per target)
 
 **Work Required**:
 
-1. **x86_64 System V** (1.5-2 weeks):
-   - Implement `va_list`, `va_start`, `va_arg`, `va_end`
-   - Handle register save area (168 bytes)
-   - Track GP vs FP registers separately
-   - 30+ tests
+1. **x86_64 System V Varargs** (1.5-2 weeks):
+   - Implement `va_list` type lowering
+   - Implement `va_start` (initialize va_list from register save area)
+   - Implement `va_arg` (extract next argument, handle types)
+   - Implement `va_end` (cleanup)
+   - Handle register save area allocation (176 bytes: 6 GP * 8 + 8 FP * 16)
+   - Track GP registers (RDI, RSI, RDX, RCX, R8, R9) vs FP registers (XMM0-XMM7) separately
+   - Handle overflow to stack for arguments beyond 6+8 registers
+   - Test with printf/scanf (30+ tests)
+
+2. **AArch64 PCS Varargs** (1.5-2 weeks):
+   - Different `va_list` structure (5 fields: gp_offset, fp_offset, overflow_arg_area, reg_save_area, etc.)
+   - Stack-based varargs with register overflow area
+   - Implement va_start/va_arg/va_end/va_copy
+   - Handle alignment requirements (8-byte GP, 16-byte FP)
+   - Register save area is stack-based (not pre-allocated)
+   - Test with printf/scanf (30+ tests)
+
+3. **Testing & Edge Cases** (3-5 days):
+   - Test varargs calling conventions (60+ tests total)
+   - Handle va_copy edge cases
+   - Validate against classic codegen
+   - Mixed GP/FP argument scenarios
+
+**Decision Point**: **Week 1** - ask Andy if varargs is graduation blocker (don't wait for Week 2)
+
+**Impact on Timeline**:
+- **If Required**: 15 weeks → 17-19 weeks total
+- **If Deferred**: Stay on 13-15 week timeline, add varargs post-graduation
 
-2. **AArch64 PCS** (1.5-2 weeks):
-   - Different `va_list` structure
-   - Stack-based varargs
-   - 30+ tests
+**Recommendation**: **Assume varargs IS required** and budget 17-19 weeks, not 15 weeks
 
-#### Phase 7: Documentation (Week 19)
+### Phase 7: Documentation (Week 19)
 
 1. API documentation
 2. User guide for adding new dialects
 3. Target implementation guide
-4. Design rationale
+4. Design rationale document
 
-### Resource Requirements
+**Deliverable**: Comprehensive documentation
 
-**Engineering Time**:
-- Primary Developer: 1 FTE for 17-19 weeks
-- Code Reviews: 2-4 hours/week from 2 reviewers
-- FIR Collaboration: Week 4 check-in
+### Phase 8: FIR Prototype (Future)
 
-**Total Investment**: ~500 engineering hours (~$85-110K)
+1. Work with FIR team on requirements
+2. Implement ABITypeInterface for FIR types
+3. Implement FIRABIRewriteContext
+4. Create FIR calling convention pass
+5. Validate with Fortran test cases
 
-**ROI**: Saves 2-3 months per additional dialect (~$100K+ each)
+**Deliverable**: Proof of concept for FIR
 
----
+**Note**: This phase is post-graduation and not included in the 17-19 week timeline.
 
-## Target ABI Details
+## VI. Target-Specific Details
 
-### x86_64 System V ABI
+### 6.1 x86_64 System V ABI
 
 **Reference**: [System V AMD64 ABI](https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf)
 
@@ -427,25 +822,29 @@ class CIRABIRewriteContext : public ABIRewriteContext {
 - FP arguments in XMM0-XMM7
 - Return in RAX/RDX (integer) or XMM0/XMM1 (FP)
 - Structs classified by 8-byte chunks
+- Memory arguments passed on stack
 
 **Classification Algorithm**:
 1. Divide type into 8-byte chunks
-2. Classify each chunk (INTEGER, SSE, X87, MEMORY, NOCLASS)
+2. Classify each chunk (Integer, SSE, X87, Memory, NoClass)
 3. Merge adjacent chunks
 4. Post-merge cleanup
 5. Map to registers or memory
 
-**Critical Edge Case: `__int128` vs `_BitInt(128)`**
+**Edge Case: `__int128` vs `_BitInt(128)`**
 
 These types have the same size (16 bytes) but **different ABI classification**:
-- `__int128`: **INTEGER** class → passed in RDI + RSI
+- `__int128`: **INTEGER** class → passed in RDI + RSI (return: RAX + RDX)
 - `_BitInt(128)`: **MEMORY** class → passed indirectly via hidden pointer
+- `_BitInt(64)`: **INTEGER** class → passed in single register RDI
 
-**Why This Matters**: Implementation must use `ABITypeInterface` methods `isInt128()` and `isBitInt()` to distinguish correctly.
+**Why This Matters**: Same size, different calling convention. Implementation must use ABITypeInterface methods `isInt128()` and `isBitInt()` to distinguish these types correctly.
 
 **Implementation Status**: ✅ Already implemented in CIR incubator
 
-### AArch64 Procedure Call Standard
+**Migration Effort**: Low - mainly replacing CIR type checks
+
+### 6.2 AArch64 Procedure Call Standard
 
 **Reference**: [ARM AArch64 ABI](https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst)
 
@@ -463,285 +862,563 @@ These types have the same size (16 bytes) but **different ABI classification**:
 
 **Implementation Status**: ✅ Already implemented in CIR incubator
 
----
-
-## Critical Decisions
-
-### 1. TargetInfo Dependency ⚠️ **HIGH PRIORITY**
+**Migration Effort**: Low - similar to x86_64
 
-**Issue**: Should MLIR-agnostic ABI code depend on `clang::TargetInfo`?
+### 6.3 Future Targets
 
-**Context**: The CIR incubator uses `clang::TargetInfo` to query target properties (pointer width, alignment, etc.). This creates an MLIR→Clang dependency.
+**Candidates** (if time permits):
+- ARM32 (for embedded systems)
+- RISC-V (emerging importance)
+- WebAssembly (for WASM backends)
+- PowerPC (for HPC systems)
 
-#### Three Options
+**Not Priority**: MIPS, Sparc, Hexagon, etc. (less common)
 
-| Option | Approach | Pros | Cons | Effort |
-|--------|----------|------|------|--------|
-| **A** | `llvm::Triple` + `DataLayoutInterface` + MLIR attributes | Clean layering, MLIR-idiomatic | Need to define ~10-15 attributes | 3-5 days |
-| **B** | Keep `clang::TargetInfo` | Zero effort, mature | **MLIR→Clang dependency violates principles** | 0 days |
-| **C** | Minimal `mlir::target::TargetInfo` | Clean layering | Duplicates Clang knowledge | 1-2 weeks |
+## VII. Testing Strategy
 
-#### Recommendation: Option A (VERIFY THEN COMMIT)
+### 7.1 Unit Tests
 
-**Rationale**:
-- ✅ **MLIR Independence**: Maintains MLIR as peer to Clang
-- ✅ **Architectural Correctness**: TargetInfo is input/metadata, should be expressible in MLIR
-- ✅ **Reasonable Effort**: 3-5 days with clear path forward
-- ✅ **Upstream Acceptance**: MLIR maintainers will approve
+**Type Interface Tests**:
+```cpp
+TEST(ABITypeInterface, IntegerQueries) {
+  MLIRContext ctx;
+  Type intTy = cir::IntType::get(&ctx, 32, true);
+  auto abiTy = dyn_cast<ABITypeInterface>(intTy);
+  EXPECT_TRUE(abiTy.isInteger());
+  EXPECT_FALSE(abiTy.isRecord());
+}
+```
 
-**Option A Approach**:
+**Classification Tests**:
 ```cpp
-// Instead of clang::TargetInfo, use:
-llvm::Triple triple;                      // From LLVM (arch/OS/vendor)
-mlir::DataLayoutSpecInterface layout;     // From MLIR (sizes/alignments)
-mlir::ModuleOp attributes;                // Target-specific properties
+TEST(X86_64ABI, SimpleIntReturn) {
+  // Setup
+  MLIRContext ctx;
+  X86_64ABIInfo abi(...);
+  Type i32 = IntegerType::get(&ctx, 32);
+  
+  // Classify
+  ABIArgInfo info = abi.classifyReturnType(i32);
+  
+  // Verify
+  EXPECT_TRUE(info.isDirect());
+  EXPECT_FALSE(info.isIndirect());
+}
+```
 
-// Example queries:
-unsigned ptrWidth = layout.getTypeSizeInBits(ptrType);
-bool isLittleEndian = triple.isLittleEndian();
+**Lowering Tests**:
+```cpp
+TEST(CIRCallConv, FunctionRewrite) {
+  // Create function with struct argument
+  // Run CallConvLowering pass
+  // Verify function signature changed correctly
+  // Verify call sites updated
+}
 ```
 
-**Why Not Option B**:
-- ❌ **Breaks MLIR Independence**: MLIR is peer to Clang, not dependent
-- ❌ **Upstream Rejection Risk**: MLIR maintainers will likely request MLIR-native approach
-- ⚠️ **False Economy**: Zero implementation time now, but redesign later if rejected
+### 7.2 Integration Tests
 
-**Decision Timeline**: **End of Week 2**
+**ABI Compliance Tests**:
+- Generate test cases using Clang classic codegen
+- Lower same functions with CIR
+- Compare LLVM IR output after lowering to LLVM
+- Ensure calling conventions match
 
-**Week 2 Go/No-Go Criteria**:
+**Cross-Dialect Tests** (future):
+- CIR function calling FIR function
+- FIR function calling CIR function
+- Verify ABI compatibility
 
-**🟢 GREEN (Proceed)**:
-- TargetInfo usage: ≤30 methods → Option A feasible
-- CIR coupling: ≤250 type cast sites
-- Total additional risk: ≤2 weeks
+### 7.3 Performance Tests
 
-**🟡 YELLOW (Proceed with Caution)**:
-- TargetInfo usage: 31-40 methods → Option A challenging
-- CIR coupling: 251-350 sites
-- Total additional risk: 2.5-4 weeks → 17-19 week timeline
+**Compilation Time**:
+- Measure time to run CallConvLowering pass
+- Compare with CIR incubator implementation
+- Target: < 5% overhead
 
-**🔴 RED (Pivot to Strategy 1)**:
-- TargetInfo usage: >40 methods → Option C required (+2 weeks)
-- CIR coupling: >350 sites (+2 weeks)
-- Total additional risk: >4 weeks → **Pivot to graduate with current implementation**
+**Generated Code Quality**:
+- Compare with classic codegen output
+- Check for unnecessary copies or spills
+- Verify register allocation is similar
 
-### 2. Varargs Support ⚠️ **LIKELY REQUIRED**
+## VIII. Migration from CIR Incubator
 
-**Issue**: CIR incubator has many `NYI` assertions for varargs. Real-world C code (printf, scanf, logging) heavily uses varargs.
+### 8.1 Migration Steps
 
-**Assessment**:
-- **Probability Required**: 70-80% (most C programs use printf/scanf)
-- **Impact if Deferred**: ~40% of C code would be unusable
-- **Graduation Risk**: Reviewers may block graduation without varargs
+1. **Parallel Implementation**:
+   - Build new MLIR-agnostic infrastructure
+   - Keep CIR incubator code working
+   - Test new infrastructure alongside old
 
-**Recommendation**: **Assume varargs IS required** and budget 17-19 weeks, not 15 weeks
+2. **Incremental Switchover**:
+   - Replace one component at a time
+   - ABIArgInfo first (easiest)
+   - Then LowerFunctionInfo
+   - Then target implementations
+   - Finally, pass structure
 
-**Decision Timeline**: **Week 1** (ask Andy immediately during validation)
+3. **Validation**:
+   - Run both old and new implementations
+   - Compare results
+   - Fix discrepancies
 
-### 3. FIR (Fortran) Coordination
+4. **Upstream Submission**:
+   - Submit shared infrastructure to MLIR
+   - Submit CIR adaptations to CIR upstream
+   - Deprecate incubator implementation
 
-**Week 4 Check-In**: Validate ABITypeInterface/ABIRewriteContext for Fortran needs
+### 8.2 Compatibility Considerations
 
-**Fortran-Specific Challenges**:
+**Source Compatibility**:
+- New ABIArgInfo API should match old API where possible
+- Minimize changes to target implementations
+- Provide migration utilities if API changes
 
-1. **CHARACTER Types** (hidden length parameter):
-   - gfortran passes length AFTER all explicit args
-   - `foo(x, str, y)` → `foo(x, str_data, y, str_len)`
-   - Requires ABIRewriteContext extension for hidden arguments
+**Binary Compatibility**:
+- Not a concern (no ABI for internal compiler structures)
 
-2. **Array Descriptors**:
-   - Fortran arrays have descriptors (bounds, strides, pointer)
-   - Need representation in ABITypeInterface
+**Test Migration**:
+- Port existing CIR tests to new infrastructure
+- Ensure all test cases still pass
+- Add new tests for edge cases
 
-**FIR Integration Estimate**: 1,000-1,200 lines (vs 800-1,000 for C-like dialects)
+### 8.3 Deprecation Plan
 
----
+Once new implementation is stable:
+1. Mark CIR incubator implementation as deprecated (Month 1)
+2. Update documentation to point to new implementation (Month 1)
+3. Keep old code for 1-2 releases for safety (Months 1-6)
+4. Remove old implementation (Month 6+)
 
-## Testing Strategy
+## IX. Future Work
 
-### ABI Compliance Tests (650+ total)
+### 9.1 Additional Targets
 
-#### 1. Systematic Tests (500+)
+- RISC-V (emerging ISA, growing importance)
+- WebAssembly (for web-based backends)
+- ARM32 (for embedded systems)
+- PowerPC (for HPC)
 
-**x86_64 System V** (250 tests):
-- Basic types: int, float, __int128, _BitInt (20 tests)
-- Structs: 1-byte, 2-byte, 4-byte, 8-byte, 9-byte, 16-byte (100 tests)
-- Unions: FP+integer, multiple FP, nested (30 tests)
-- Arrays: Fixed-size, multi-dimensional (20 tests)
-- Edge cases: empty structs, bitfields, over-aligned (50 tests)
-- Varargs: printf/scanf edge cases (30 tests)
+### 9.2 Advanced Features
 
-**AArch64 PCS** (250 tests):
-- Basic types (20 tests)
-- HFA/HVA detection: 1-5 fields, nested, mixed types (80 tests - **CRITICAL**)
-- Structs: various sizes and alignments (80 tests)
-- Over-alignment: 16, 32, 64-byte aligned (30 tests)
-- Edge cases: empty structs, padding (40 tests)
+**Varargs Support**:
+- Currently marked NYI in CIR
+- Need to handle variable argument lowering
+- Different per target (va_list representation varies)
 
-#### 2. Differential Tests (100+)
+**Microsoft ABI**:
+- Windows calling conventions
+- MSVC C++ ABI
+- Different from Itanium C++ ABI
 
-- Compare generated assembly vs classic Clang
-- Real-world struct layouts from open-source projects
-- Ensures ABI compliance
+**Swift Calling Convention**:
+- Swift-specific argument passing
+- Error handling conventions
+- Async conventions
 
-#### 3. Interoperability Tests (50+)
+**Vector ABI**:
+- SIMD type passing
+- SVE (ARM Scalable Vector Extension)
+- AVX-512 considerations
 
-- Actual C→CIR→C function calls
-- Runtime binary compatibility verification
+### 9.3 Optimization Opportunities
 
-### Performance Benchmarks
+**Return Value Optimization (RVO)**:
+- Avoid copies for returned aggregates
+- Requires coordination with frontend
 
-**Compilation Time**:
-- Target: < 5% overhead (classic Clang ABI lowering adds ~1-2%)
-- Measurement: Profile on LLVM test-suite
-- Note: This is **compile-time** overhead, not runtime
+**Tail Call Optimization**:
+- Recognize tail call patterns
+- Lower to tail call convention
 
----
+**Inlining-Aware Lowering**:
+- Delay ABI lowering until after inlining
+- Can avoid unnecessary marshalling
 
-## Success Metrics
+### 9.4 GSoC Integration
 
-### Functional Metrics
+**Monitor GSoC Progress**:
+- Track PR #140112 development
+- Assess fit with MLIR needs
+- Plan integration if beneficial
 
-- ✅ CIR can lower x86_64 calling conventions (100% test pass)
-- ✅ CIR can lower AArch64 calling conventions (100% test pass)
-- ✅ ABI output matches classic Clang codegen
-- ✅ All CIR incubator tests pass with new implementation
+**Potential Integration**:
+- Use GSoC's ABI type system
+- Wrap GSoC ABIInfo implementations
+- Share test cases and validation
 
-### Quality Metrics
+**Timeline**:
+- Short term (Q1 2026): Implement MLIR-native solution
+- Medium term (Q2-Q3 2026): Evaluate GSoC library
+- Long term (Q4 2026+): Potentially refactor to use GSoC
 
-- ✅ Code coverage > 90% for ABI classification logic
-- ✅ Zero known ABI compliance bugs
-- ✅ Documentation complete
+## X. Open Questions and Risks
 
-### Performance Metrics
+### 10.1 Open Questions
 
-- ✅ CallConvLowering pass overhead < 5% compilation time
-- ✅ No degradation in generated code quality
+1. **Should we use TypeInterface or helper class for type queries?**
+   - TypeInterface is more MLIR-idiomatic but requires modifying type definitions
+   - Helper class is more flexible but adds indirection
+   - **Recommendation**: TypeInterface for better integration
 
-### Reusability Metrics
+2. **How to handle clang::TargetInfo dependency in MLIR?** ⚠️ **CRITICAL DECISION REQUIRED**
 
-- ✅ FIR can adopt infrastructure with < 2 weeks integration effort
-- ✅ New target can be added with < 1 week effort
-- ✅ Per-dialect cost: 800-1,000 lines of code
+**Background**: The CIR incubator currently uses `clang::TargetInfo` (from `clang/include/clang/Basic/TargetInfo.h`) to query target-specific properties (pointer width, alignment, endianness, etc.) needed for ABI decisions. Moving this to MLIR-agnostic infrastructure raises the question: should MLIR code depend on a Clang library?
 
----
+**The Issue**: 
+- `clang::TargetInfo` lives in `clangBasic` library
+- Creating dependency: `mlir/lib/Target/ABI/` → `clang/include/clang/Basic/`
+- MLIR policy generally avoids depending on Clang (peer relationship, not hierarchical)
+- However, this is target-specific infrastructure, not core MLIR
 
-## Multi-Dialect Support
+**What TargetInfo Provides** (~20-30 methods used by ABI code):
+- Pointer size and alignment
+- Integer/float type sizes
+- Maximum alignment
+- Endianness
+- Calling conventions available for target
+- Target triple information
+- ABI-specific flags (e.g., passes objects in registers)
 
-### Per-Dialect Integration Cost
+---
 
-**CIR** (C-like dialects):
-- ABITypeInterface: 800-1,000 lines
-- ABIRewriteContext: 300-500 lines
-- **Total**: < 2 weeks engineering time
+**Option A: Use llvm::Triple + MLIR DataLayoutInterface**
 
-**FIR** (Fortran-specific):
-- ABITypeInterface: 1,000-1,200 lines
-- CHARACTER hidden length handling
-- Array descriptor representation
-- **Total**: ~2-3 weeks engineering time
+**Approach**: Combine existing LLVM/MLIR infrastructure:
+```cpp
+// Instead of clang::TargetInfo, use:
+llvm::Triple triple;                      // From LLVM (arch/OS/vendor)
+mlir::DataLayoutSpecInterface layout;     // From MLIR (sizes/alignments)
+mlir::ModuleOp attributes;                // Target-specific properties
 
-### Benefits
+// Example queries:
+unsigned ptrWidth = layout.getTypeSizeInBits(ptrType);
+bool isLittleEndian = triple.isLittleEndian();
+```
 
-**For CIR**:
-- Correctness: Proven ABI compliance
-- Maintainability: Share updates with other dialects
-- Upstream Path: Clear acceptance path
+**Pros**:
+- ✅ No Clang dependency (clean layering)
+- ✅ Uses existing MLIR patterns (DataLayoutInterface)
+- ✅ MLIR-idiomatic approach
+- ✅ Works with any MLIR dialect
 
-**For FIR**:
-- Reduced Effort: < 3 weeks vs 3 months from scratch
-- Correctness: Reuse battle-tested ABI logic
-- Interoperability: Guaranteed compatibility with C/C++ code
+**Cons**:
+- ⚠️ Need to define module-level attributes for ~10-15 ABI properties
+- ⚠️ Upfront design work (2-3 days)
+- ⚠️ Less comprehensive than TargetInfo (may need to add properties later)
 
-**For LLVM Community**:
-- Code Reuse: Future dialects get calling convention support "for free"
-- Consistency: Single source of truth for ABI rules
-- Quality: Shared testing and validation
+**Effort**: ~3-5 days design + implementation
 
 ---
 
-## Future Work
+**Option B: Keep Using clang::TargetInfo**
 
-### Additional Targets
+**Approach**: Accept MLIR→Clang dependency for target-specific code:
+```cpp
+// Continue using what works:
+const clang::TargetInfo &Target;
+unsigned ptrWidth = Target.getPointerWidth(0);
+bool isLittleEndian = Target.isLittleEndian();
+```
 
-- RISC-V (emerging ISA)
-- WebAssembly (for web-based backends)
-- ARM32 (for embedded systems)
-- PowerPC (for HPC)
+**Pros**:
+- ✅ Zero implementation time (already done)
+- ✅ Mature, comprehensive (500+ lines of target properties)
+- ✅ Battle-tested across all Clang targets
+- ✅ No duplication of knowledge
+- ✅ Actually target-agnostic despite the name/location
 
-### Advanced Features
+**Cons**:
+- ❌ Creates MLIR→Clang dependency (architectural concern)
+- ❌ May be rejected by MLIR maintainers
+- ⚠️ Lives in `clang/Basic/` (naming suggests Clang-specific)
 
-**Microsoft ABI**:
-- Windows calling conventions
-- MSVC C++ ABI
-- Estimated: 4-6 weeks
+**Risk**: If rejected during review, need to pivot to Option A or C (adds 1-3 weeks delay)
 
-**C++ Non-Trivial Types** (Phase 2):
-- Non-trivial copy constructors
-- Non-trivial destructors
-- Move-only types
+---
 
-**Optimization Opportunities**:
-- Return Value Optimization (RVO)
-- Tail Call Optimization
-- Inlining-Aware Lowering
+**Option C: Minimal MLIR-Native TargetInfo**
 
-### GSoC Integration
+**Approach**: Create lightweight `mlir::target::TargetInfo` abstraction:
+```cpp
+// mlir/include/mlir/Target/TargetInfo.h
+namespace mlir::target {
+class TargetInfo {
+public:
+  static std::unique_ptr<TargetInfo> create(llvm::Triple, DataLayoutSpec);
+  
+  virtual unsigned getPointerWidth(unsigned AddrSpace) const = 0;
+  virtual unsigned getMaxAlignment() const = 0;
+  virtual bool isLittleEndian() const = 0;
+  // ... ~15-20 methods total for ABI needs
+};
 
-**Monitor GSoC Progress**:
-- Track PR #140112 development
-- Assess fit with MLIR needs
-- Plan integration if beneficial
+// Per-target implementations
+class X86_64TargetInfo : public TargetInfo { ... };
+class AArch64TargetInfo : public TargetInfo { ... };
+}
+```
 
-**Timeline**:
-- Short term (Q1 2026): Implement MLIR-native solution
-- Medium term (Q2-Q3 2026): Evaluate GSoC library
-- Long term (Q4 2026+): Potentially refactor to use GSoC
+**Pros**:
+- ✅ No Clang dependency (clean layering)
+- ✅ Tailored specifically for ABI lowering needs
+- ✅ Can evolve independently
+
+**Cons**:
+- ❌ Duplicates information from clang::TargetInfo (~200 lines per target)
+- ❌ More code to maintain
+- ❌ Implementation effort: ~200 lines × 2 targets = 400 lines
+- ⚠️ May need to sync with Clang when targets evolve
+
+**Effort**: ~1-2 weeks implementation + testing
 
 ---
 
-## Risk Assessment
+**Recommendation**: **Option A (Triple + DataLayoutInterface)** - VERIFY FEASIBILITY, then commit
 
-| Risk | Probability | Impact | Mitigation |
-|------|-------------|--------|------------|
-| **TargetInfo dependency rejected** | Medium (30%) | High (+1-3 weeks) | Week 1-2 validation, Option A prototype ready |
-| **Varargs required for graduation** | High (70-80%) | High (+3-4 weeks) | Assume required, budget 17-19 weeks |
-| **CIR coupling deeper than expected** | Medium (30%) | Medium (+0.5-1 week) | Week 1 audit reveals actual coupling |
-| **Performance overhead > 5%** | Low | High | Profile early, optimize hot paths, caching |
-| **ABI compliance bugs** | Low | Critical | Extensive testing vs classic codegen |
+**Priority Order**:
+1. **Option A** (PREFERRED) - MLIR-native, architecturally correct
+2. **Option C** (FALLBACK) - If Option A insufficient, create minimal MLIR TargetInfo
+3. **Option B** (NOT RECOMMENDED) - MLIR→Clang dependency violates MLIR architecture principles
 
-**Overall Risk**: **Medium** - Key architectural decision (TargetInfo) must be resolved in Week 2.
+**Rationale**:
 
----
+**Why Option A is Preferred**:
+- ✅ **MLIR Independence**: Maintains MLIR as peer to Clang, not dependent
+- ✅ **Architectural Correctness**: TargetInfo is input/metadata, should be expressible in MLIR
+- ✅ **Reasonable Effort**: 3-5 days with clear path forward
+- ✅ **MLIR-Idiomatic**: Uses DataLayoutInterface and module attributes (standard patterns)
+- ✅ **Upstream Acceptance**: MLIR maintainers will approve this approach
+
+**Why Option B is NOT Recommended**:
+- ❌ **Breaks MLIR Independence**: MLIR is peer to Clang, not dependent (architectural principle)
+- ❌ **Upstream Rejection Risk**: MLIR maintainers will likely request MLIR-native approach
+- ❌ **Wrong Precedent**: `mlir/lib/Target/` dependencies should be for output formats (LLVM IR, SPIR-V), not input metadata
+- ⚠️ **False Economy**: Zero implementation time now, but redesign later if rejected
+
+**Why Option C is Acceptable Fallback**:
+- ✅ **Architecturally Sound**: MLIR-native, clean layering
+- ✅ **Tailored for ABI**: Only ~15-20 methods needed (not 500+ like clang::TargetInfo)
+- ✅ **Upstream Acceptable**: MLIR maintainers will approve
+- ⚠️ **Higher Effort**: 1-2 weeks vs 3-5 days for Option A
+- ⚠️ **Duplication**: Some overlap with clang::TargetInfo knowledge
+
+**MLIR Architect Perspective**:
+> "MLIR's mission is to be reusable by Rust, Julia, Swift, etc. without requiring Clang. TargetInfo is metadata/input (not an output format like LLVM IR), so it should be expressible in MLIR. Option B breaks this principle. I would request changes in upstream review."
+
+**Decision Timeline**:
+- **Weeks 1-2 (Validation Phase - Days 1-10)**: Complete all audits and prototype
+  - Audit actual TargetInfo usage in CIR incubator
+  - Generate concrete list of methods/properties needed
+  - Identify which are covered by DataLayout vs need attributes
+  - Design Option A with concrete module attributes
+  - Define exact attribute schema (names, types, defaults)
+  - Prototype with x86_64 ABI queries
+  - Validate DataLayoutInterface provides what we need
+- **End of Week 2 (Day 10)**: Go/No-Go Decision
+  - ✅ **If Option A is sufficient** → Commit to Option A, proceed to Phase 1
+  - ❌ **If Option A has gaps** → Assess: can we add attributes? Or need Option C?
+  - 🔴 **If Option C required AND adds >2 weeks** → Pivot to Strategy 1 (graduate with current impl)
+
+**Weeks 1-2 Exit Criteria (Validation Phase)**:
+```
+[ ] Complete audit of TargetInfo usage (concrete method list)
+[ ] Audit CIR coupling depth (count dyn_cast<cir::Type> sites)
+[ ] Audit ABITypeInterface requirements (list exact methods needed)
+[ ] Audit ABIRewriteContext requirements (list exact methods needed)
+[ ] Draft module attribute schema for Option A
+[ ] Prototype Option A with 1 target (x86_64) proving feasibility
+[ ] Ask Andy: Is varargs required for graduation?
+[ ] Decision: A (commit) or C (fallback) or Strategy 1 (pivot)
+[ ] Apply Weeks 1-2 Pivot Thresholds (Green/Yellow/Red)
+```
 
-## References
+**Weeks 1-2 Pivot Thresholds** (Go/No-Go Decision):
 
-### ABI Specifications
+**🟢 GREEN (Proceed with Strategy 2)**:
+- TargetInfo usage: ≤30 methods → Option A feasible
+- CIR coupling: ≤250 type cast sites → Phase 3 on schedule
+- Interface complexity: ≤20 methods per interface → Phase 2 on schedule
+- Varargs: Deferred (confirmed by Andy)
+- **Total Additional Risk**: ≤2 weeks → 15-17 week timeline acceptable → **PROCEED**
+
+**🟡 YELLOW (Proceed with Caution)**:
+- TargetInfo usage: 31-40 methods → Option A challenging, might need Option C
+- CIR coupling: 251-350 sites → Phase 3 +1 week
+- Interface complexity: 21-25 methods → Phase 2 +0.5 weeks
+- Varargs: Required for graduation (likely)
+- **Total Additional Risk**: 2.5-4 weeks → 17-19 week timeline → **PROCEED WITH BUFFER**
+
+**🔴 RED (Pivot to Strategy 1)**:
+- TargetInfo usage: >40 methods → Option C required (+2 weeks)
+- CIR coupling: >350 sites → Phase 3 +2 weeks
+- Interface complexity: >25 methods → Phase 2 +1 week
+- Multiple blockers simultaneously
+- **Total Additional Risk**: >4 weeks → 19-21 week timeline → **PIVOT TO STRATEGY 1**
+
+**Strategy 1 Pivot**: Graduate with current CIR-specific implementation, refactor upstream later
+
+**Fallback Strategy**:
+If Option A requires Option C, and Option C adds >2 weeks to timeline (total >3 weeks for TargetInfo resolution), consider graduating with current CIR-specific implementation and refactoring upstream (Strategy 1 pivot).
+
+3. **Where should code be located?**
+
+**ABITypeInterface**:
+- **Location**: `mlir/include/mlir/Interfaces/ABI/ABITypeInterface.td`
+- **Rationale**: Cross-dialect interface, follows MLIR convention
+
+**ABIArgInfo, LowerFunctionInfo, ABIRewriteContext** (shared structures):
+- **Location**: `mlir/include/mlir/Interfaces/ABI/`
+- **Rationale**: Shared data structures and interfaces used by all dialects
+
+**ABIInfo, Target Implementations**:
+- **Location**: `mlir/include/mlir/Target/ABI/`
+- **Rationale**: Target-specific classification logic, matches MLIR precedent
+- **Precedent**: `mlir/include/mlir/Target/LLVMIR/`, `mlir/include/mlir/Target/SPIRV/`
+- **MLIR Convention**: `Interfaces/` is for cross-dialect, `Target/` is for target-specific
+
+**Recommendation**: This split follows MLIR conventions correctly
+
+4. **ABIRewriteContext vs OpBuilder + Interfaces?** ⚠️ **TO BE VALIDATED IN WEEK 1**
+
+**Current Design**: Custom `ABIRewriteContext` interface for dialect-specific operations
+
+**MLIR Architect Concern**: MLIR already has operation abstractions (`OpBuilder`, `FunctionOpInterface`, `CallOpInterface`)
+
+**Alternative Approach**:
+```cpp
+// Instead of custom ABIRewriteContext:
+// Use existing MLIR interfaces + OpBuilder directly
+template<typename FuncOpT, typename CallOpT>
+  requires FunctionOpInterface<FuncOpT> && CallOpInterface<CallOpT>
+class ABILowering {
+  OpBuilder &builder;
+  // No virtual calls, use concrete types
+};
+```
+
+**Week 1 Task**: Prototype both approaches
+- **Option 1**: Custom ABIRewriteContext (current design)
+- **Option 2**: OpBuilder + existing interfaces (template-based)
+- **Decision Criteria**: Code clarity, maintainability, performance
+
+**Not a Blocker**: Both approaches work. Choose based on prototype results.
+
+5. **How to coordinate with FIR team?**
+   - When to engage them?
+   - Who owns the shared infrastructure?
+   - **Recommendation**: Build CIR-first, engage FIR team at Phase 7 (after CIR proven)
+
+### 10.2 Risks
+
+**Risk 1: TargetInfo Dependency Rejected** ⚠️ **CRITICAL**
+- **Impact**: High (could add 1-3 weeks to timeline)
+- **Probability**: Medium (30-40%)
+- **Description**: MLIR maintainers may reject `clang::TargetInfo` dependency, requiring MLIR-native implementation
+- **Mitigation**: 
+  - Weeks 1-2 (Validation Phase): Design MLIR-native alternative (Option A)
+  - Get early feedback from Andy and MLIR maintainers
+  - Audit actual TargetInfo usage to minimize required functionality
+  - Have fallback implementation ready
+- **Fallback**: If adds >2 weeks, pivot to Strategy 1 (graduate with current implementation)
+
+**Risk 2: GSoC Library Divergence**
+- **Impact**: Medium
+- **Probability**: Medium
+- **Description**: Parallel development with GSoC project could create incompatible approaches
+- **Mitigation**: Stay in contact with GSoC author, plan integration path, share design early
+
+**Risk 3: Performance Overhead**
+- **Impact**: High (if > 10% overhead)
+- **Probability**: Low
+- **Description**: Abstraction layers could introduce unacceptable compile-time overhead
+- **Mitigation**: Profile early, optimize hot paths, consider caching, benchmark against classic codegen
+
+**Risk 4: Incomplete Target Support Blocks Graduation** ⚠️ **HIGH PROBABILITY**
+- **Impact**: High (blocks graduation)
+- **Probability**: **High (70-80%)** - varargs likely required
+- **Description**: Missing features (varargs, complex types) may be required for graduation
+- **Specific Issue**: CIR incubator has many `NYI` for varargs; ~40% of C code uses printf/scanf
+- **Mitigation**: 
+  - **Week 1**: Ask Andy explicitly: "Is varargs required for graduation?"
+  - Budget 17 weeks (not 15) to account for likely varargs requirement
+  - Have varargs implementation plan ready (2-3 weeks)
+  - Focus on x86_64/AArch64 Linux (80% of use cases)
+  - Document limitations clearly if varargs deferred
+
+**Risk 5: Breaking Changes in MLIR**
+- **Impact**: Medium
+- **Probability**: Low
+- **Description**: MLIR interface changes could break our implementation
+- **Mitigation**: Follow MLIR development, use stable interfaces, engage with MLIR community
+
+**Risk 6: Complexity Underestimation**
+- **Impact**: High (timeline slip)
+- **Probability**: Medium
+- **Description**: Edge cases and corner cases in ABI handling are complex
+- **Mitigation**: Incremental development, frequent validation against classic codegen, comprehensive testing
+
+## XI. Success Metrics
+
+### 11.1 Functional Metrics
+
+- ✅ CIR can lower x86_64 calling conventions correctly (100% test pass rate)
+- ✅ CIR can lower AArch64 calling conventions correctly (100% test pass rate)
+- ✅ ABI output matches classic Clang codegen (validated by comparison tests)
+- ✅ All CIR incubator tests pass with new implementation
+
+### 11.2 Quality Metrics
+
+- ✅ Code coverage > 90% for ABI classification logic
+- ✅ Zero known ABI compliance bugs
+- ✅ Documentation complete (API, user guide, design rationale)
+
+### 11.3 Performance Metrics
+
+- ✅ CallConvLowering pass overhead < 5% compilation time
+  - **Context**: This refers to **compile-time overhead**, not runtime performance
+  - **Baseline**: Classic Clang ABI lowering adds ~1-2% to compile time
+  - **Target**: MLIR-agnostic version should be ≤2.5× classic overhead (5% total)
+  - **Measurement**: Profile on LLVM test-suite, measure time in ABI classification
+  - **Optimization Strategies**: Cache ABITypeInterface queries, fast-path for primitives
+- ✅ No degradation in generated code quality vs direct implementation
+  - **Runtime performance unchanged**: ABI lowering is compile-time only
+
+### 11.4 Reusability Metrics
+
+- ✅ FIR can adopt infrastructure with < 2 weeks integration effort
+- ✅ New target can be added with < 1 week effort (given ABI spec)
+- ✅ ABITypeInterface requires < 10 methods implementation per dialect
+
+## XII. References
+
+### 12.1 ABI Specifications
 
 - [System V AMD64 ABI](https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf)
 - [ARM AArch64 PCS](https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst)
 - [Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html)
 
-### LLVM/MLIR Documentation
+### 12.2 LLVM/MLIR Documentation
 
 - [MLIR Interfaces](https://mlir.llvm.org/docs/Interfaces/)
 - [MLIR Type System](https://mlir.llvm.org/docs/DefiningDialects/AttributesAndTypes/)
 - [MLIR Pass Infrastructure](https://mlir.llvm.org/docs/PassManagement/)
 
-### Related Projects
+### 12.3 Related Projects
 
 - [GSoC ABI Lowering RFC](https://discourse.llvm.org/t/rfc-an-abi-lowering-library-for-llvm/84495)
 - [GSoC PR #140112](https://github.com/llvm/llvm-project/pull/140112)
 - [CIR Project](https://github.com/llvm/clangir)
 
-### Related Implementation
+### 12.4 Related Implementation
 
 - Clang CodeGen: `clang/lib/CodeGen/`
 - CIR Incubator: `clang/lib/CIR/Dialect/Transforms/TargetLowering/`
+- SPIR-V ABI: `mlir/lib/Dialect/SPIRV/IR/TargetAndABI.cpp`
 
----
+## XIII. Appendices
 
-## Appendix: Glossary
+### A. Glossary
 
 - **ABI**: Application Binary Interface
 - **CC**: Calling Convention
@@ -751,12 +1428,86 @@ bool isLittleEndian = triple.isLittleEndian();
 - **HVA**: Homogeneous Short-Vector Aggregate (ARM term)
 - **NYI**: Not Yet Implemented
 - **PCS**: Procedure Call Standard (ARM term)
+- **RVO**: Return Value Optimization
 
----
+### B. File Structure Summary
 
-**Contact**: Adam Smith (CIR Team)  
-**Last Updated**: January 2026
+```
+mlir/
+├── include/mlir/Interfaces/ABI/
+│   ├── ABITypeInterface.td
+│   ├── ABIArgInfo.h
+│   ├── LowerFunctionInfo.h
+│   └── ABIRewriteContext.h
+├── include/mlir/Target/ABI/
+│   ├── ABIInfo.h
+│   └── TargetRegistry.h
+├── lib/Interfaces/ABI/
+│   ├── ABIArgInfo.cpp
+│   ├── LowerFunctionInfo.cpp
+│   └── CMakeLists.txt
+└── lib/Target/ABI/
+    ├── ABIInfo.cpp
+    ├── TargetRegistry.cpp
+    ├── X86/
+    │   ├── X86_64ABIInfo.h/cpp
+    │   └── CMakeLists.txt
+    ├── AArch64/
+    │   ├── AArch64ABIInfo.h/cpp
+    │   └── CMakeLists.txt
+    └── CMakeLists.txt
+
+clang/lib/CIR/Dialect/Transforms/TargetLowering/
+├── CallConvLowering.cpp         # CIR-specific pass
+├── CIRABIRewriteContext.h/cpp   # CIR operation rewriting
+└── CMakeLists.txt
+```
+
+### C. Implementation Checklist
+
+**Phase 1: Infrastructure**
+- [ ] Create directory structure
+- [ ] Move ABIArgInfo
+- [ ] Define ABITypeInterface
+- [ ] Define ABIRewriteContext
+- [ ] Setup build system
+
+**Phase 2: CIR Integration**
+- [ ] Implement ABITypeInterface for CIR types
+- [ ] Implement CIRABIRewriteContext
+- [ ] Add type query tests
+
+**Phase 3: Target ABI**
+- [ ] Extract X86_64ABIInfo
+- [ ] Extract AArch64ABIInfo
+- [ ] Create TargetRegistry
+- [ ] Add classification tests
+
+**Phase 4: Lowering Pass**
+- [ ] Create CallConvLowering pass
+- [ ] Function signature rewriting
+- [ ] Call site rewriting
+- [ ] Value coercion
+- [ ] Integration tests
+
+**Phase 5: Testing**
+- [ ] Port CIR tests
+- [ ] ABI compliance tests
+- [ ] Performance benchmarks
+- [ ] Bug fixes
+
+**Phase 6: Varargs**
+- [ ] x86_64 varargs implementation
+- [ ] AArch64 varargs implementation
+- [ ] Varargs tests (60+)
+
+**Phase 7: Documentation**
+- [ ] API documentation
+- [ ] User guide
+- [ ] Target guide
+- [ ] Design document
 
 ---
 
-*This design builds on the proven foundation of the CIR incubator implementation while extending it to be reusable by the broader MLIR ecosystem. Community feedback is welcomed and encouraged.*
+**Contact**: Adam Smith (CIR Team)  
+**Last Updated**: January 2026

>From cf23d362644ea567ab5d08d95b8d52f662e7858f Mon Sep 17 00:00:00 2001
From: Adam Smith <adams at nvidia.com>
Date: Wed, 28 Jan 2026 10:34:58 -0800
Subject: [PATCH 3/3] [ClangIR] Add ClangIRABILowering to documentation index

Add ClangIRABILowering.md to the Design Documents section
of clang/docs/index.rst to fix Sphinx build error.
---
 clang/docs/index.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 70c8737a2fe0d..a12042851f0ee 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -122,6 +122,7 @@ Design Documents
    HardwareAssistedAddressSanitizerDesign.rst
    ConstantInterpreter
    ClangIRCodeDuplication
+   ClangIRABILowering
 
 Indices and tables
 ==================



More information about the cfe-commits mailing list