[clang] [CIR] Add support for lowering __builtin_c23_va_start in ClangIR (PR #208741)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 10 07:53:19 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Akshay K (kumarak)
<details>
<summary>Changes</summary>
C23 `va_start `expands to `__builtin_c23_va_start`, which was previously routed to the unimplemented-builtin NYI path in ClangIR. As a result, variadic code failed to compile with -fclangir in -std=c23 mode.
This change lowers `__builtin_c23_va_start` the same way as `__builtin_va_start`. For both builtins, the va_list operand is always argument 0, so the existing lowering logic can be reused directly.
---
Full diff: https://github.com/llvm/llvm-project/pull/208741.diff
2 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+1)
- (added) clang/test/CIR/CodeGen/var_arg-c23.c (+45)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 3c48b8b67d9ee..84bb33663de05 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1059,6 +1059,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
// C stdarg builtins.
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
+ case Builtin::BI__builtin_c23_va_start:
case Builtin::BI__va_start: {
mlir::Value vaList = builtinID == Builtin::BI__va_start
? emitScalarExpr(e->getArg(0))
diff --git a/clang/test/CIR/CodeGen/var_arg-c23.c b/clang/test/CIR/CodeGen/var_arg-c23.c
new file mode 100644
index 0000000000000..729b93bc6ceb3
--- /dev/null
+++ b/clang/test/CIR/CodeGen/var_arg-c23.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+// Ensure that __builtin_va_start(list, 0) and __builtin_c23_va_start(list)
+// have the same codegen, mirroring clang/test/CodeGen/varargs.c. The LLVM
+// checks are shared between the ClangIR pipeline and OG CodeGen.
+
+void noargs(...) {
+ __builtin_va_list list;
+ __builtin_va_start(list, 0);
+ __builtin_c23_va_start(list);
+ __builtin_va_end(list);
+}
+
+// CIR-LABEL: cir.func {{.*}} @noargs(
+// CIR: %[[VAAREA:.+]] = cir.alloca "list" {{.*}} : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
+// CIR: %[[VA_PTR0:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]]
+// CIR-NEXT: cir.va_start %[[VA_PTR0]] : !cir.ptr<!rec___va_list_tag>
+// CIR: %[[VA_PTR1:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]]
+// CIR-NEXT: cir.va_start %[[VA_PTR1]] : !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va_end %{{.+}} : !cir.ptr<!rec___va_list_tag>
+
+// LLVM-LABEL: define {{.*}}void @noargs(...)
+// LLVM: %[[VAAREA:.+]] = alloca [1 x %struct.__va_list_tag]
+// LLVM: call void @llvm.va_start.p0(ptr %{{.+}})
+// LLVM: call void @llvm.va_start.p0(ptr %{{.+}})
+// LLVM: call void @llvm.va_end.p0(ptr %{{.+}})
+
+void with_param(int count, ...) {
+ __builtin_va_list list;
+ __builtin_c23_va_start(list, count);
+ __builtin_va_end(list);
+}
+
+// CIR-LABEL: cir.func {{.*}} @with_param(
+// CIR: cir.va_start %{{.+}} : !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va_end %{{.+}} : !cir.ptr<!rec___va_list_tag>
+
+// LLVM-LABEL: define {{.*}}void @with_param(i32 noundef %{{.+}}, ...)
+// LLVM: call void @llvm.va_start.p0(ptr %{{.+}})
+// LLVM: call void @llvm.va_end.p0(ptr %{{.+}})
``````````
</details>
https://github.com/llvm/llvm-project/pull/208741
More information about the cfe-commits
mailing list